How to set exposure registers on AR1820HS jetson camera?

The command I am using to do it is
sudo python3 rw_sensor.py -d 0 -r 12306 -v 500

I also tried different values other than 500 for exposure like 100.

but it doesn’t seem to change the exposure when I take a photo using this python script.

import cv2
import argparse
from utils import ArducamUtils
import RPi.GPIO as GPIO
import _thread
import uuid
import time
import v4l2

def fourcc(a, b, c, d):
    return ord(a) | (ord(b) << 8) | (ord(c) << 16) | (ord(d) << 24)

def pixelformat(string):
    if len(string) != 3 and len(string) != 4:
        msg = "{} is not a pixel format".format(string)
        raise argparse.ArgumentTypeError(msg)
    if len(string) == 3:
        return fourcc(string[0], string[1], string[2], ' ')
    else:
        return fourcc(string[0], string[1], string[2], string[3])

def show_info(arducam_utils):
    _, firmware_version = arducam_utils.read_dev(ArducamUtils.FIRMWARE_VERSION_REG)
    _, sensor_id = arducam_utils.read_dev(ArducamUtils.FIRMWARE_SENSOR_ID_REG)
    _, serial_number = arducam_utils.read_dev(ArducamUtils.SERIAL_NUMBER)
    print("Firmware Version: {}".format(firmware_version))
    print("Sensor ID: 0x{:04X}".format(sensor_id))
    print("Serial Number: 0x{:08X}".format(serial_number))

# for executing a thread to save the image.
def save_image(data):
    cv2.imwrite("/home/dlinano/photos/imagetest" + str(uuid.uuid1()) + ".png", data)
    print("finished execution")

# Initialize the camera
print("Initializing camera")
images = []
cap = cv2.VideoCapture(0, cv2.CAP_V4L2)
# set pixel format
if not cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc('Y', '1', '6', ' ')):
    print("Failed to set pixel format.")

arducam_utils = ArducamUtils(0)

show_info(arducam_utils)
# turn off RGB conversion
if arducam_utils.convert2rgb == 0:
    cap.set(cv2.CAP_PROP_CONVERT_RGB, arducam_utils.convert2rgb)

# set width
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 4896)
# set height
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 3684)

ret, frame = cap.read()

print("Starting demo now! Press CTRL+C to exit")

print("Capture")
ret, frame = cap.read()
frame = arducam_utils.convert(frame)
_thread.start_new_thread(save_image, tuple([frame]))

I tried running the command before I initialize the camera in the script and after.

I am really new to using cameras this close to hardware where I am manually setting registers. Is it possible to adapt the code in the RPi section to do this?

Time to answer my own question. You can set the exposure using v4l-utils using the command

v4l2-ctl --device /dev/video0 -c exposure=100

100 being the exposure level you want which ranges from 0 to 65535

and I guess I can just do that in a python script using the os library. Maybe v4l2 for python also allows you to do this somehow.

Great!

I can’t set the register on ov2311 and ov7251. Using v4l2-ctl or rw_sensor.py just change nothing…

sudo python3 rw_sensor.py -d 0 -r 0x3501 -v 1024

Hi @jjehl ,

You need to initialize the camera before reading and writing registers or use v4l2-ctl.

Hi,

What du you mean by “initialize” ? The camera is plugged on the MIPI port. I can get an image using OpenCV, I can read the register as you can see on my capture screen with :

v4l2-ctl --all
But it is just not possible to write a new value for any of the registers users should be able to control (exposure, gain ....).

Can you provide a code example to illustrate what you mean by “initialize”.

Regards.

I can change the exposure but the process is really weird, I need to purge 6 frames and to change 6 times the exposure, if not the default exposure came back when reading the frame :

# -*- coding: utf-8 -*- """ Created on Wed Oct 14 18:52:54 2020

@author: julien
“”"
import cv2
from utils import ArducamUtils
import subprocess
import time

def show_info(arducam_utils):
_, firmware_version = arducam_utils.read_dev(ArducamUtils.FIRMWARE_VERSION_REG)
_, sensor_id = arducam_utils.read_dev(ArducamUtils.FIRMWARE_SENSOR_ID_REG)
_, serial_number = arducam_utils.read_dev(ArducamUtils.SERIAL_NUMBER_REG)
print(“Firmware Version: {}”.format(firmware_version))
print(“Sensor ID: 0x{:04X}”.format(sensor_id))
print(“Serial Number: 0x{:08X}”.format(serial_number))

def resize(frame, dst_width):
width = frame.shape[1]
height = frame.shape[0]
scale = dst_width * 1.0 / width
return cv2.resize(frame, (int(scale * width), int(scale * height)))

cmd1 = ‘v4l2-ctl -d 0 -c exposure=50’
cmd2 = ‘v4l2-ctl -d 0 -C exposure’
cap = cv2.VideoCapture(0, cv2.CAP_V4L2)
arducam_utils = ArducamUtils(0)
cap.set(cv2.CAP_PROP_CONVERT_RGB, arducam_utils.convert2rgb)
show_info(arducam_utils)

w = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
h = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)

list_frame=[]

needed to purge the frame with default exposure

for i in range(6):
subprocess.call(cmd1, shell=True)
ret, frame = cap.read()

loop to process the image at manual exposure

for i in range(100):
ret, frame = cap.read()
list_frame.append(frame)

for index,frame in enumerate(list_frame):
frame = frame.reshape(int(h), int(w))
frame = arducam_utils.convert(frame)

frame = resize(frame, 1280.0)

cv2.imwrite(‘test’+str(index)+’.jpg’,frame)


 

The default exposure also come back when camera is disconnected.

Hi @jjehl

Initializing the camera means to make the camera work, relative to the code, it is to open the camera and read a frame of image.
So you just need to do this:
cap = cv2.VideoCapture(0, cv2.CAP_V4L2)

cap.read() # or using cap.grap()
Modify the exposure here.

After modifying the exposure, there will be a certain number of frames that have not been modified. These frames are stored in the cache.

 

The default exposure also come back when camera is disconnected.
The camera does not store the last exposure value. When you disconnect or turn off the camera and turn it on again, the exposure value will be restored to the default value.