How to fine tune the arducam mipi camera image quality manually?

Published by bin on

Home Forums Cameras Modules for Raspberry Pi Arducam MIPI Camera Modules How to fine tune the arducam mipi camera image quality manually?

Viewing 6 reply threads
  • Author
    Posts
    • #13740
      bin
      Keymaster

      At present, due to the image sensor now has no built-in ISP, how to get the ideal image quality is the problem we have to overcome. Arducam now release a serial of mipi cameras, due to not have the raspberrypi official local hardware ISP support, Arducam technical team release some software ways to fine tune the image quality. The target of this topic is to tell user to how to use Arducam mipi api to tune the image quality.

      Now Arducam mipi camera’s API supports adjust the exposure time and gain compensation manually.  The related API is int arducam_set_control(CAMERA_INSTANCE camera_instance, int ctrl_id, int value)  

      * @param camera_instance Type CAMERA_INSTANCE, Obtained from arducam_init_camera function.

      * @param ctrl_id Control id.

      * @param value Control value.

      * @return error code , 0 success, !0 error.

      * example:

      @code

      arducam_set_control(camera_instance, V4L2_CID_EXPOSURE, 3000);

      @endcode

      * */

      About the control ID, user can run ./list_format to check all the ID your sensor support.

      In this topic, I use the imx298 as an example.

      list_format guide

      For example, If I set the exposure time to 0x00FF

      If I set the exposure time to 0x0F00

      User can enabe and disable the auto white balance using the int arducam_software_auto_white_balance(CAMERA_INSTANCE camera_instance, int enable) API.

      If set arducam_software_auto_white_balance(camera_instance, 0), the image will be green

      If set arducam_software_auto_white_balance(camera_instance, 1), the image will be betterhttps://www.arducam.com/wp-content/uploads/hm_bbpui/13740/2z5o94pucz69bgpt146t0krsa97yp2zo.png

      Sometimes, after we enable the auto white balance, we can’t get the better image quality we need, we can use void arducam_manual_set_awb_compensation(uint32_t r_gain, uint32_t b_gain) API to compensation the red channel gain and blue channel gain.

      User can use arducamstill command to test.

      run ./arducamstill -? to get the help

      For example if I set rgain to 100 and bgain to 150
      [email protected]:~/MIPI_Camera/RPI $ ./arducamstill -t 0 -rgain 100 -bgain 150

      For example if I set rgain to 150 and bgain to 50
      [email protected]:~/MIPI_Camera/RPI $ ./arducamstill -t 0 -rgain 150 -bgain 50

      What’s more , for some lens support motor focus, about the focus control, user can use  arducam_set_control(camera_instance, V4L2_CID_FOCUS_ABSOLUTE, value) API.

      For example, if I set the value to 10

      arducam_set_control(camera_instance, V4L2_CID_FOCUS_ABSOLUTE, 10)

      The image will be blurring

      If set the value to 190

      arducam_set_control(camera_instance, V4L2_CID_FOCUS_ABSOLUTE, 190)

      The image will be better.

      Now, we release opencvGui demo and Video presentation. Visiting  https://www.arducam.com/downloads/video/Arducam_Fine_Tune_Method_for_MIPI_Cameras.mp4

       

       

      • This topic was modified 6 months, 3 weeks ago by Lee Jackson.
      • This topic was modified 4 months, 3 weeks ago by bin.
    • #14203
      Agris Reppo
      Guest

      Hello!

      I dont know why, but when I use mode 2 with this code, it takes green pictures sometimes. I have original mipicamera library. Can you help? I am beginner as you can see. I changed capture.c code to have almost good solution. Only problem is that mode 3 makes pictures about 10 mb, but mode 2 does it with 2,5mb. I dont see very big difference in resolutions. Also that program takes pictures of moving objects, about 5-10cm/s. Sometimes blur occurs. My code is below. Thank you!

      #include “arducam_mipicamera.h”
      #include <linux/v4l2-controls.h>
      #include <stdio.h>
      #include <string.h>
      #include <time.h>
      #include <unistd.h>
      #include <time.h> ///////////////

      #define LOG(fmt, args…) fprintf(stderr, fmt “\n”, ##args)

      #define FOCUS_VAL 310 //range(0-65535) /// FOOKUSE SEADISTAMINE 50cm = 300
      /// 40cm = 310
      #define SOFTWARE_AE_AWB
      //IMAGE_ENCODING_JPEG
      //IMAGE_ENCODING_BMP
      //IMAGE_ENCODING_PNG
      IMAGE_FORMAT fmt = {IMAGE_ENCODING_JPEG, 50};

      void save_image(CAMERA_INSTANCE camera_instance, const char *name) {

      arducam_set_control(camera_instance, V4L2_CID_FOCUS_ABSOLUTE, 315); // fookus

      arducam_set_control(camera_instance, V4L2_CID_EXPOSURE, 500); //valguse sättimine //500

      //arducam_software_auto_exposure(camera_instance, 1);

      arducam_software_auto_white_balance(camera_instance, 1);

      usleep(1000 * 1000 * 1);

      usleep(1000*10);
      BUFFER *buffer = arducam_capture(camera_instance, &fmt, 12000);
      if (!buffer) {
      LOG(“capture timeout.”);
      return;
      }
      FILE *file = fopen(name, “wb”);
      fwrite(buffer->data, buffer->length, 1, file);
      fclose(file);
      arducam_release_buffer(buffer);
      }

      int main(int argc, char **argv) {

      CAMERA_INSTANCE camera_instance;

      ////int width = 2336, height = 1748; /// vali mode 2
      //// int width = 4672, height = 3496; /// vali mode 3

      char file_name[100];
      time_t rawtime;////////////// Thu Dec 5 15:54:56 2019.jpg
      struct tm * timeinfo;////////////
      time ( &rawtime );////////////////////
      timeinfo = localtime ( &rawtime );//////////////////
      //////
      time_t timer; ////////////////06-12-2019 08.35.29
      char buffer[26];
      struct tm* tm_info;
      time(&timer);
      tm_info = localtime(&timer);
      strftime(buffer, 26, “%d-%m-%Y %H.%M.%S”, tm_info);
      puts(buffer);
      ////
      LOG(“Open camera…”);
      int res = arducam_init_camera(&camera_instance);
      if (res) {
      LOG(“init camera status = %d”, res);
      return -1;
      }

      int mode = 3;////3 highest // mode 2 compensation 55, 200
      arducam_manual_set_awb_compensation(60,200); // 150, 255 arducam_manual_set_awb_compensation(r_gain_conpensation,b_gain_conpensation);

      LOG(“Setting the mode…”);
      //res = arducam_set_resolution(camera_instance, &width, &height);
      res= arducam_set_mode(camera_instance, mode);

      if (res) {
      LOG(“set resolution status = %d”, res);
      return -1;
      } else {
      LOG(“Current mode is %d”, mode);
      }

      if(fmt.encoding == IMAGE_ENCODING_JPEG){
      // sprintf(file_name, “/home/pi/Desktop/Pildid/capture %s.jpg”, asctime (timeinfo));///////////
      //sprintf(file_name, “/home/pi/Public/Avalik/RaspberryPi/capture %s.jpg”, asctime (timeinfo));///////////
      sprintf(file_name, “/home/pi/Public/Avalik/RaspberryPi/capture %s.jpg”, buffer);
      }

      LOG(“Capture image %s…”, file_name);
      save_image(camera_instance, file_name);

      LOG(“Close camera…”);
      res = arducam_close_camera(camera_instance);
      if (res) {
      LOG(“close camera status = %d”, res);
      }
      return 0;
      }

       

      • #14206
        bin
        Keymaster

        Different mode means different resolution. In different resolution, some time you should fine tune the gain.

    • #14262
      Agris Reppo
      Guest

      I have tried it without success. Its pretty random I think, few pictures okay, then few pictures green. Frist picture green, five sec later, without green. I dont know, but with higher resolution that problem never occurs.

      https://www.arducam.com/wp-content/uploads/hm_bbpui/14262/bt4tcls627xylgfgslda4n8s98l77ax0.jpg

      • #14267
        bin
        Keymaster

        It seems the time of auto white balance is not enough. Please try to add more delay to wait it auto white balance finished. You can try change the 1 to 3 or 5

    • #14324
      Agris Reppo
      Guest

      Hello!

      That really works! Thanks, you are genius. I dont know why I didnot notice that line of code. I thought something with white balance. It worked (usleep (1000 * 1000 * 3))

      • #14328
        bin
        Keymaster

        Hello,

        You are welcome. It is my duty  to help you solve problems.

        Let me know if you need more help.

         

    • #14380
      gorski
      Guest

      <p style=”text-align: left;”>hey,</p>
      thanks for the support!

      i was curious what would be the recommended procedure to get 2 or more differently exposed images as fast as possible from the raspberry and ar1820. preferably raw without further image processing.  would it be possible for you to implement some sort of auto exposure bracketing with the sensor or will the hdr mode be available? why is not possible to change exposure time via api in capture_raw program?

      thanks again for your work.

      regards,

      gorski

      • #14388
        bin
        Keymaster

        Hi,

        The ar1820 does not support HDR mode, You can set the exposure time using

        arducam_set_control(camera_instance, V4L2_CID_EXPOSURE, 500); //valguse sättimine //500

    • #21274
      andreavaresio
      Participant

      I have an issue in controlling manually the AR1820 sensor. I cannot
      change the exposure, gain, Red balance and Blue balance.

      I attached a modified version of your source code (capture.c) that
      parses from the command line the exposure,gain,rbal and bbal values,
      disables any automatic control and set them before capturing.

      usage: capture exposure gain rbal bbal

      Trying to setup 1 or 65000 as exposure provide the same output . It seems the setting is not applied. 8I tried also with other values)

      ./capture 1 16 64 64

      ./capture 65000 16 64 64

       

       

      Here the code

      #include “arducam_mipicamera.h”
      #include <linux/v4l2-controls.h>
      #include <stdio.h>
      #include <string.h>
      #include <time.h>
      #include <unistd.h>
      #include <stdlib.h>
      #define LOG(fmt, args…) fprintf(stderr, fmt “\n”, ##args)

      //IMAGE_ENCODING_JPEG
      //IMAGE_ENCODING_BMP
      //IMAGE_ENCODING_PNG
      IMAGE_FORMAT fmt = {IMAGE_ENCODING_JPEG, 100};
      void save_image(CAMERA_INSTANCE camera_instance, const char *name) {

      // The actual width and height of the IMAGE_ENCODING_RAW_BAYER format and the IMAGE_ENCODING_I420 format are aligned,
      // width 32 bytes aligned, and height 16 byte aligned.
      usleep(1000*10);
      BUFFER *buffer = arducam_capture(camera_instance, &fmt, 12000);
      if (!buffer) {
      LOG(“capture timeout.”);
      return;
      }
      FILE *file = fopen(name, “wb”);
      fwrite(buffer->data, buffer->length, 1, file);
      fclose(file);
      arducam_release_buffer(buffer);
      }

      int main(int argc, char **argv) {
      if (argc!=5)
      {
      LOG(“usage capture exposure gain rgain bgain”);
      exit(1);
      }

      CAMERA_INSTANCE camera_instance;
      int width = 0, height = 0;
      char file_name[100];

      LOG(“Open camera…”);
      int res = arducam_init_camera(&camera_instance);
      if (res) {
      LOG(“init camera status = %d”, res);
      return -1;
      }

      struct format support_fmt;
      int index = 0;
      char fourcc[5];
      fourcc[4] = ‘\0’;
      while (!arducam_get_support_formats(camera_instance, &support_fmt, index++)) {
      strncpy(fourcc, (char *)&support_fmt.pixelformat, 4);
      LOG(“mode: %d, width: %d, height: %d, pixelformat: %s, desc: %s”,
      support_fmt.mode, support_fmt.width, support_fmt.height, fourcc,
      support_fmt.description);
      }
      index = 0;
      struct camera_ctrl support_cam_ctrl;
      while (!arducam_get_support_controls(camera_instance, &support_cam_ctrl, index++)) {
      int value = 0;
      if (arducam_get_control(camera_instance, support_cam_ctrl.id, &value)) {
      LOG(“Get ctrl %s fail.”, support_cam_ctrl.desc);
      }
      LOG(“index: %d, CID: 0x%08X, desc: %s, min: %d, max: %d, default: %d, current: %d”,
      index – 1, support_cam_ctrl.id, support_cam_ctrl.desc, support_cam_ctrl.min_value,
      support_cam_ctrl.max_value, support_cam_ctrl.default_value, value);
      }
      int mode = 4;
      int exposure = atoi(argv[1]);
      int gain = atoi(argv[2]);
      int rbal = atoi(argv[3]);
      int bbal= atoi(argv[4]);

      LOG(“Setting the mode…”);
      // res = arducam_set_resolution(camera_instance, &width, &height);
      printf(“choose the mode %d\r\n”, mode );
      res= arducam_set_mode(camera_instance, mode);
      if (res) {
      LOG(“set resolution status = %d”, res);
      return -1;
      } else {
      LOG(“Current mode is %d”, mode);
      LOG(“Notice:You can use the list_format sample program to see the resolution and control supported by the camera.”);
      }

      if (arducam_reset_control(camera_instance, V4L2_CID_FOCUS_ABSOLUTE)) {
      LOG(“Failed to set focus, the camera may not support this control.”);
      }

      if (arducam_software_auto_exposure(camera_instance, 0)) {
      LOG(“ailed to switch off auto exposure.”);
      }

      if (arducam_software_auto_white_balance(camera_instance, 0)) {
      LOG(“ailed to switch off auto WB.”);
      }

      printf(“setting exposure %d\n”, exposure);
      if (arducam_set_control(camera_instance, V4L2_CID_EXPOSURE, exposure)) {
      LOG(“Failed to set exposure, the camera may not support this control.”);
      }

      printf(“setting gain %d\n”, gain);
      if (arducam_set_control(camera_instance, V4L2_CID_GAIN, gain)) {
      LOG(“Failed to set gain, the camera may not support this control.”);
      }

      printf(“setting r/b bal %d %d\n”, rbal, bbal);
      arducam_manual_set_awb_compensation(rbal, bbal);

      if(fmt.encoding == IMAGE_ENCODING_JPEG){
      sprintf(file_name, “mode%d.jpg”, mode);
      }
      if(fmt.encoding == IMAGE_ENCODING_BMP){
      sprintf(file_name, “mode%d.bmp”, mode);
      }
      if(fmt.encoding == IMAGE_ENCODING_PNG){
      sprintf(file_name, “mode%d.png”, mode);
      }
      LOG(“Capture image %s…”, file_name);
      save_image(camera_instance, file_name);

      LOG(“Close camera…”);
      res = arducam_close_camera(camera_instance);
      if (res) {
      LOG(“close camera status = %d”, res);
      }
      return 0;
      }

    • #21467
      bin
      Keymaster

      Hi,

      Sorry for my later reply due to my ill. We have release arducamstill demo and it support getting image in different encode format.Please try to use arducamstill demo, you can get the user guide here: https://github.com/ArduCAM/MIPI_Camera/tree/master/RPI

       

       

Viewing 6 reply threads
  • You must be logged in to reply to this topic.