Unable to change picture settings with python/opencv

1.Which seller did you purchase the product(s) from?
Amazon
2.The Model number of the product(s) you have purchased?
13MP AR1335 OBISP MIPI Camera Module
3.Which Platform are you using the product(s) on?
Pi 4
4.Which instruction are you following?
https://www.arducam.com/docs/arducam-obisp-mipi-camera-module/3-use-on-raspberry-pi/3-9-test-samples/
5.Has your product ever worked properly?
To be decided :slight_smile:
6.What problems are you experiencing?
I am having issues with my python program taking consistent pictures and setting camera properties for optimal photographs with opencv using the same method as the documentation linked above.

I am able to successfully see the picture of the camera change according to settings when I use the shell programpi@raspberrypi:~ $ v4l2-ctl -d /dev/video0 -c exposure=50000
pi@raspberrypi:~ $ v4l2-ctl -d /dev/video0 -c white_balance_automatic=1
pi@raspberrypi:~ $ v4l2-ctl -d /dev/video0 -c zoom=2

I can observe these changes when streaming with gstreamer over netcat (arducamstill -t 0 -e h264 -o stdout | nc -l -p 5000) or using arducamstill. I can get the picture to look the way I want this way.

When I use OpenCV within python I do not see that these changes. First I tried setting them like in the example linked above.

subprocess.call([‘v4l2-ctl -d /dev/video0 -c ircut=1’],shell=True)

I noticed that opencv may have its own way to set attributes. So I tried this:

cap = cv2.VideoCapture(0)

cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter.fourcc(*“UYVY”))
cap.set(cv2.CAP_PROP_FRAME_WIDTH,4160) #set width
cap.set(cv2.CAP_PROP_FRAME_HEIGHT,3120) #set height
cap.set(cv2.CAP_PROP_AUTO_EXPOSURE, 0)
cap.set(cv2.CAP_PROP_GAMMA, 4000)
cap.set(cv2.CAP_PROP_AUTO_WB, 0)

Other than setting the correct resolution I am not able to see any changes in the picture I have taken. They look very unusual and over-exposed without changing these settings. I used code to attempt to find supported settings:

supported = list()
for attr in dir(cv2):
if attr.startswith(‘CAP_PROP’):
if cap.get(getattr(cv2, attr)) != -1:
print(attr)

And I receive the following:

CAP_PROP_AUTO_EXPOSURE
CAP_PROP_AUTO_WB
CAP_PROP_BACKEND
CAP_PROP_BUFFERSIZE
CAP_PROP_CONTRAST
CAP_PROP_CONVERT_RGB
CAP_PROP_FORMAT
CAP_PROP_FOURCC
CAP_PROP_FRAME_HEIGHT
CAP_PROP_FRAME_WIDTH
CAP_PROP_GAIN
CAP_PROP_GAMMA
CAP_PROP_MODE
CAP_PROP_POS_MSEC
CAP_PROP_SATURATION
CAP_PROP_SHARPNESS
CAP_PROP_TEMPERATURE
CAP_PROP_WB_TEMPERATURE
CAP_PROP_ZOOM

It seems like these should be supported but I am not seeing the properties do anything (aside from resolution)

Here is a photo with arducamstill

https://imgur.com/a/DXCspM1

Here is a similar photo with opencv

https://imgur.com/a/WgsqSd9

The opencv looks very odd because I cannot adjust the properties
7.What attempts at troubleshooting have you already made?
Described in post
8.How would you like us to help you?
Please help me figure out how to adjust exposure, brightness, gamma etc that affect OpenCV photos in python

Hello,

Strange phenomenon. As normal, we use subprocess.call([‘v4l2-ctl -d /dev/video0 -c ircut=1’],shell=True) to set control paramter.

Would you like to attach me your source code and I can help you test it in detail and fix it?

 

Bin,

Thank you for taking the time to reply. I have modified the example code to perform a few camera tests to reproduce the issue. After more experiments the last 2 days it seems only sometimes these commands work when I run the script the first time but after that they do not and I have to reboot if there is any hope of them working again.

import numpy as np import cv2 import v4l2 import time import subprocess cap = cv2.VideoCapture(0)

cap.set(cv2.CAP_PROP_FRAME_WIDTH,2560) #set width
cap.set(cv2.CAP_PROP_FRAME_HEIGHT,1440) #set height
cap.grab()
cap.grab()
time.sleep(0.1)

subprocess.call([‘v4l2-ctl -d /dev/video0 -c ircut=1’],shell=True)
time.sleep(0.1)
print(“ircut=1”)
cap.grab()
ret, frame = cap.read()
cv2.imwrite(“image_ircut_1.jpg”,frame)

subprocess.call([‘v4l2-ctl -d /dev/video0 -c ircut=0’],shell=True)
time.sleep(0.5)
print(“ircut=0”)
cap.grab()
ret,frame2 = cap.read()
cv2.imwrite(“image_ircut_0.jpg”,frame2)

subprocess.call([‘v4l2-ctl -d /dev/video0 -c horizontal_flip=1’],shell=True)
time.sleep(0.5)
print(“horizontal_flip=1”)
cap.grab()
ret,frame2 = cap.read()
cv2.imwrite(“image_horizontal_flip_1.jpg”,frame2)

subprocess.call([‘v4l2-ctl -d /dev/video0 -c vertical_flip=1’],shell=True)
time.sleep(0.5)
print(“vertical_flip=1”)
cap.grab()
ret,frame2 = cap.read()
cv2.imwrite(“image_vertical_flip_1.jpg”,frame2)

subprocess.call([‘v4l2-ctl -d /dev/video0 -c zoom=2’],shell=True)
time.sleep(0.5)
print(“zoom=2”)
cap.grab()
ret,frame2 = cap.read()
cv2.imwrite(“image_zoom_2.jpg”,frame2)

subprocess.call([‘v4l2-ctl -d /dev/video0 -c contrast=100’],shell=True)
time.sleep(0.5)
print(“contrast=100”)
cap.grab()
ret,frame2 = cap.read()
cv2.imwrite(“image_contrast_100.jpg”,frame2)

cap.release()


ircut=1

ircut=1

ircut=0

ircut=0

horizontal_flip=1

horizontal_flip=1

vertical_flip=1

vertical_flip=1

zoom=2

zoom=2

contrast=100

contrast=100.

In the examples attached ircut might work (picture changes color) but the flip, zoom and contrast all do not. It seems the camera quickly quits responding to commands. I am using the 5.4.79-v7l+ driver that was recently released with a fresh OS install.

pi@raspberrypi:~ $ uname -a
Linux raspberrypi 5.4.79-v7l+ #4 SMP Thu Dec 10 10:08:29 CST 2020 armv7l GNU/Linux

Hoping you see what might be going wrong. I am suspecting the newer driver or something wrong with the camera. Something else suspicious I noticed when using arducamstill, a complaint about no mach to hardware version.

pi@raspberrypi:~ $ arducamstill -o test5.jpg -w 4160 -h 3120
Hardare version: a03111
No match to hardware version!
Device /dev/video0) opened.
Video format set: UYVY (59565955) 4160x3120
[Framerate]: 07 fps.
Saving image data to test5.jpg successfully.

Bin,

Thank you for taking the time to reply. I have modified the example code to perform a few camera tests to reproduce the issue. After more experiments the last 2 days it seems only sometimes these commands work when I run the script the first time but after that they do not and I have to reboot if there is any hope of them working again.

import numpy as np import cv2 import v4l2 import time import subprocess cap = cv2.VideoCapture(0)

cap.set(cv2.CAP_PROP_FRAME_WIDTH,2560) #set width
cap.set(cv2.CAP_PROP_FRAME_HEIGHT,1440) #set height
cap.grab()
cap.grab()
time.sleep(0.1)

subprocess.call([‘v4l2-ctl -d /dev/video0 -c ircut=1’],shell=True)
time.sleep(0.1)
print(“ircut=1”)
cap.grab()
ret, frame = cap.read()
cv2.imwrite(“image_ircut_1.jpg”,frame)

subprocess.call([‘v4l2-ctl -d /dev/video0 -c ircut=0’],shell=True)
time.sleep(0.5)
print(“ircut=0”)
cap.grab()
ret,frame2 = cap.read()
cv2.imwrite(“image_ircut_0.jpg”,frame2)

subprocess.call([‘v4l2-ctl -d /dev/video0 -c horizontal_flip=1’],shell=True)
time.sleep(0.5)
print(“horizontal_flip=1”)
cap.grab()
ret,frame2 = cap.read()
cv2.imwrite(“image_horizontal_flip_1.jpg”,frame2)

subprocess.call([‘v4l2-ctl -d /dev/video0 -c vertical_flip=1’],shell=True)
time.sleep(0.5)
print(“vertical_flip=1”)
cap.grab()
ret,frame2 = cap.read()
cv2.imwrite(“image_vertical_flip_1.jpg”,frame2)

subprocess.call([‘v4l2-ctl -d /dev/video0 -c zoom=2’],shell=True)
time.sleep(0.5)
print(“zoom=2”)
cap.grab()
ret,frame2 = cap.read()
cv2.imwrite(“image_zoom_2.jpg”,frame2)

subprocess.call([‘v4l2-ctl -d /dev/video0 -c contrast=100’],shell=True)
time.sleep(0.5)
print(“contrast=100”)
cap.grab()
ret,frame2 = cap.read()
cv2.imwrite(“image_contrast_100.jpg”,frame2)

cap.release()


ircut=1

ircut=1

ircut=0

ircut=0

horizontal_flip=1

horizontal_flip=1

vertical_flip=1

vertical_flip=1

zoom=2

zoom=2

contrast=100

contrast=100.

In the examples attached ircut might work (picture changes color) but the flip, zoom and contrast all do not. It seems the camera quickly quits responding to commands. I am using the 5.4.79-v7l+ driver that was recently released with a fresh OS install.

pi@raspberrypi:~ $ uname -a
Linux raspberrypi 5.4.79-v7l+ #4 SMP Thu Dec 10 10:08:29 CST 2020 armv7l GNU/Linux

Hoping you see what might be going wrong. I am suspecting the newer driver or something wrong with the camera. Something else suspicious I noticed when using arducamstill, a complaint about no mach to hardware version.

pi@raspberrypi:~ $ arducamstill -o test5.jpg -w 4160 -h 3120
Hardare version: a03111
No match to hardware version!
Device /dev/video0) opened.
Video format set: UYVY (59565955) 4160x3120
[Framerate]: 07 fps.
Saving image data to test5.jpg successfully.

Bin,

Thank you for taking the time to reply. I have modified the example code to perform a few camera tests to reproduce the issue. After more experiments the last 2 days it seems only sometimes these commands work when I run the script the first time but after that they do not and I have to reboot if there is any hope of them working again.

import numpy as np
import cv2
import v4l2
import time
import subprocess
cap = cv2.VideoCapture(0)

cap.set(cv2.CAP_PROP_FRAME_WIDTH,2560) #set width
cap.set(cv2.CAP_PROP_FRAME_HEIGHT,1440) #set height
cap.grab()
cap.grab()
time.sleep(0.1)

subprocess.call([‘v4l2-ctl -d /dev/video0 -c ircut=1’],shell=True)
time.sleep(0.1)
print(“ircut=1”)
cap.grab()
ret, frame = cap.read()
cv2.imwrite(“image_ircut_1.jpg”,frame)

subprocess.call([‘v4l2-ctl -d /dev/video0 -c ircut=0’],shell=True)
time.sleep(0.5)
print(“ircut=0”)
cap.grab()
ret,frame2 = cap.read()
cv2.imwrite(“image_ircut_0.jpg”,frame2)

subprocess.call([‘v4l2-ctl -d /dev/video0 -c horizontal_flip=1’],shell=True)
time.sleep(0.5)
print(“horizontal_flip=1”)
cap.grab()
ret,frame2 = cap.read()
cv2.imwrite(“image_horizontal_flip_1.jpg”,frame2)

subprocess.call([‘v4l2-ctl -d /dev/video0 -c vertical_flip=1’],shell=True)
time.sleep(0.5)
print(“vertical_flip=1”)
cap.grab()
ret,frame2 = cap.read()
cv2.imwrite(“image_vertical_flip_1.jpg”,frame2)

subprocess.call([‘v4l2-ctl -d /dev/video0 -c zoom=2’],shell=True)
time.sleep(0.5)
print(“zoom=2”)
cap.grab()
ret,frame2 = cap.read()
cv2.imwrite(“image_zoom_2.jpg”,frame2)

subprocess.call([‘v4l2-ctl -d /dev/video0 -c contrast=100’],shell=True)
time.sleep(0.5)
print(“contrast=100”)
cap.grab()
ret,frame2 = cap.read()
cv2.imwrite(“image_contrast_100.jpg”,frame2)

cap.release()

ircut=1

ircut=0

horizontal_flip=1

vertical_flip=1

zoom=2

contrast=100

.

In the examples attached ircut might work (picture changes color) but the flip, zoom and contrast all do not. It seems the camera quickly quits responding to commands. I am using the 5.4.79-v7l+ driver that was recently released with a fresh OS install.

pi@raspberrypi:~ $ uname -a
Linux raspberrypi 5.4.79-v7l+ #4 SMP Thu Dec 10 10:08:29 CST 2020 armv7l GNU/Linux

Hoping you see what might be going wrong. I am suspecting the newer driver or something wrong with the camera. Something else suspicious I noticed when using arducamstill, a complaint about no mach to hardware version.

pi@raspberrypi:~ $ arducamstill -o test5.jpg -w 4160 -h 3120
Hardare version: a03111
No match to hardware version!
Device /dev/video0) opened.
Video format set: UYVY (59565955) 4160x3120
[Framerate]: 07 fps.
Saving image data to test5.jpg successfully.

ircut=1

ircut=0

horizontal_flip=1

vertical_flip=1

zoom=2

contrast=100

It seems my images did not make it into the last post. I have uploaded them here

https://negentropy.space/arducam/

I have simplified the example even more. I allowed .5 seconds between each call.

import numpy as np
import cv2
import v4l2
import time
import subprocess
cap = cv2.VideoCapture(0)

while(True):
# This image should be what the other blocks of code translate
cap.grab()
ret, frame1 = cap.read()
cv2.imshow(‘Arducam ar1335 PARENT’,frame1)

# Attempt vertical flip
subprocess.call([‘v4l2-ctl -d /dev/video0 -c vertical_flip=1’],shell=True)
time.sleep(.5)
cap.grab()
ret, frame2 = cap.read()
# Undo vertical flip
subprocess.call([‘v4l2-ctl -d /dev/video0 -c vertical_flip=0’],shell=True)
cv2.imshow(‘Arducam ar1335 vertical_flip’,frame2)
time.sleep(.5)

# Attempt horizontal flip
subprocess.call([‘v4l2-ctl -d /dev/video0 -c horizontal_flip=1’],shell=True)
time.sleep(.5)
cap.grab()
ret, frame3 = cap.read()
# Undo horizontal flip
subprocess.call([‘v4l2-ctl -d /dev/video0 -c horizontal_flip=0’],shell=True)
cv2.imshow(‘Arducam ar1335 horizontal_flip’,frame3)
time.sleep(.5)

# Attempt Zoom
subprocess.call([‘v4l2-ctl -d /dev/video0 -c zoom=2’],shell=True)
time.sleep(.5)
cap.grab()
ret, frame4 = cap.read()
# Undo Zoom
subprocess.call([‘v4l2-ctl -d /dev/video0 -c zoom=1’],shell=True)
cv2.imshow(‘Arducam ar1335 zoom’,frame4)
time.sleep(.5)

print(“loop”)
cv2.waitKey(100)

cap.release()
cv2.destroyAllWindows()

Here is a video of what this looks like for me. The frames I read are completely unreliable.

https://www.youtube.com/watch?v=hOxAgAx3Sj4&feature=youtu.be

I experience the same thing when attempting to save files. Seems what I get is random if I do get an effect at all.

Another test that fails, capture one image with no settings then try to apply

“v4l2-ctl -d /dev/video0 -c vertical_flip=1 -c horizontal_flip=1 -c zoom=2”

Take another image. The result images are identical for me. I use flips because it is easiest to observe the results this way. In my project I need contrast, white balance etc but these are not as obvious and still fail in the same way.

import cv2
import time
import subprocess

cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter.fourcc(*“UYVY”))
cap.set(cv2.CAP_PROP_FRAME_WIDTH,4160) #set width
cap.set(cv2.CAP_PROP_FRAME_HEIGHT,3120) #set height
time.sleep(5)
cap.grab()
cap.grab()
cap.grab()
ret, frame = cap.read()
cv2.imwrite(“test_cv2_before.jpg”, frame)

subprocess.call([‘v4l2-ctl -d /dev/video0 -c vertical_flip=1 -c horizontal_flip=1 -c zoom=2’],shell=True)
time.sleep(5)
cap.grab()
cap.grab()
cap.grab()
ret, frame = cap.read()
cv2.imwrite(“test_cv2_after.jpg”, frame)
print("ret " + str(ret))
print(“Done”)

cap.release()

Due to the opencv has cached. After switching the state, you have to lose a few frames while fetching data.

Bin,

Thank you for the reply. I can see the issue gets better if I add 20 cap.grab() calls. I am not sure how many is actually required? I am assuming there is not a more elegant workaround than this?

Also, do you have any idea if this issue is of any concern:
“No match to hardware version!”

Thanks again for your time,

Matt

Hello, Just ignore the “No match to hardware version!” message, which is a debug message. We have added this driver to the lib. You can ignore it.

About the opencv, I am still working on it. We can work together to find a better way.

 

Hi, I was facing issues with subprocess.call(…) not having any effect too. I was not able to adjust exposure. What worked for me was to add a cap.read() right before the subprocess.call(…). Now the exposure setting gets updated properly…

Hello Matthew,

I am also struggling with this same issue of the photos being green and overexposed, but opencv is not able to change this. I was wondering if you were able to get this problem resolved, and if so if you could help me fix my issue? Thanks!

I ended up returning the camera. I easily spent 2 weeks trying to get it working better. Instead I bought the official HQ camera (new at the time) from Adafruit. It works great, highly recommend.
Raspberry Pi High Quality HQ Camera (12MP) + various lenses
You may need to rewrite some of your code, but I am much more satisfied with this camera

good luck

1 Like