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

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
pi@raspberrypi:~/MIPI_Camera/RPI $ ./arducamstill -t 0 -rgain 100 -bgain 150

For example if I set rgain to 150 and bgain to 50
pi@raspberrypi:~/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

 

 

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;
}

 

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

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

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

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))

Hello,

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

Let me know if you need more help.

 

<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

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

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;
}

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