SA-Kenan/03_Aufnahmeserie/Takeimage_Shutterspeed_PiCameraVideoPort_V01-02.py

442 lines
20 KiB
Python
Raw Normal View History

2022-05-09 20:30:26 +02:00
# Creation Date: 10.01.2022
# Author: Kenan Gömek
# This script takes pictures with Picameras VideoPort like it will be used to work with OpenCV and saves it with OpenCV to have the real use case pictures.
# Update: This script is designed to take image series with different camera parameters
# Update-Comment:
# To-DO:
import serial
import cv2 as cv
import picamera
from picamera.array import PiRGBArray
from fractions import Fraction
import time
from datetime import datetime
import os
import numpy as np
# Comment for Measurement-Log:
CAM_NR = "04" # CAM:01,02,03,04
COMMENT = ""
# Set Parameters for series with variable shutterspeeds
# Uncomment/Comment needed code parts for shutter speed lists:
#START_SHUTTER_SPEED = 50 # microseconds. 0=auto
#END_SHUTTER_SPEED = 100 # microseconds
#STEP_SHUTTER_SPEED = 25 # microseconds
# shutter_speeds_add = [47, 66, 85, 104] # microseconds. shutter speeds to additionally add
shutter_speeds_add = [50] # microseconds. shutter speeds to additionally add
# from investigations: ss < 30 are all darker, but the darkness is the same. e.g: ss=5,10,15,20,25 are all the same brightness=Shutter_speed
# with ss <5 µs (because < 20 µs) one can request the minimum posisble shutter speed
# it was found, that ss is adjustable in 20 µs-steps from 30 µs ongoing: [10 µs, 30 µs, 50 µs] in this range
# retrieved ss: 9, 28, 47, 66, 85, 104 µs
shutter_speeds = list()
#for ss in range(START_SHUTTER_SPEED, END_SHUTTER_SPEED+STEP_SHUTTER_SPEED, STEP_SHUTTER_SPEED):
# shutter_speeds.append(ss)
#shutter_speeds = shutter_speeds + shutter_speeds_add # concatenate lists
shutter_speeds = shutter_speeds_add
shutter_speeds.sort() # sort list
# camera_resolutions = [(192, 144), (416,320), (640,480), (960,720), (1280,960), (1648,1232)]
camera_resolutions = [(192, 144)]
iso_values = [320]
# Define camera settings
if CAM_NR == "03":
SENSOR_MODE = 4 # corresponding sensor mode to resolution
OUTPUT_RESOLUTION = (416, 320) # (1640x1232)/4=(410,308)
# Camera informations for log
CAM_DESCRIPTION = "Raspberry Pi Camera Module V2"
CAM_EAN = "506021437024020"
elif CAM_NR == "04":
SENSOR_MODE = 4 # corresponding sensor mode to resolution
# Camera informations for log
CAM_DESCRIPTION = "Raspberry Pi NoIR Camera Module V2"
CAM_EAN = "0640522710898"
elif CAM_NR == ("01"):
SENSOR_MODE = 4 # corresponding sensor mode to resolution --> gibt es sowas für camera 1? Ja gleicher Sensor wie Raspberry Pi V1 sensor!
# Camera informations for log
CAM_DESCRIPTION = "RPI-SPYCAM"
CAM_EAN = "4251266701743 "
elif CAM_NR == ("02"):
SENSOR_MODE = 4 # corresponding sensor mode to resolution --> gibt es sowas für camera 2? --> Ja gleicher Sensor wie Raspberry Pi V1 sensor!
# Camera informations for log
CAM_DESCRIPTION = "RB-Camera_JT"
CAM_EAN = "4250236815909"
AWB_MODE = 'off' # Auto white balance mode
# AWB_GAINS = (Fraction(485, 256), Fraction(397, 256)) # White Balance Gains to have colours read correctly: (red, blue)
AWB_GAINS = (1.395, 1.15) # White Balance Gains to have colours read correctly: (red, blue). Int, floar or fraction are valid.
BRIGHTNESS = 25 # sets the brightness setting of the camera. default is 50. [0-100]
#the brighter, the brighter the LEDs and the higher the RGB values and vice versa!
CONTRAST = 100 # sets the contrast setting of the camera. The default value is 0. [-100 ... 100]
ISO = 320 # ISO value
EXPOSURE_MODE = 'off'
FRAMERATE = 25 # frames per second. 40 fps is max for sensor mode 4
SLEEP_TIME = 2 # Time for sleep-mode for the camera in seconds. My default: 2 s
# Dictionary for color patterns
# r: red, g: green, b: blue, y: yellow, m: magenta, c: cyan
dict_color_pattern = {
"01": "rgb",
"02": "rgy",
"03": "rgm",
"04": "rgc",
"05": "rby",
"06": "rbm",
"07": "rbc",
"08": "rym",
"09": "ryc",
"10": "rmc",
"11": "gby",
"12": "gbm",
"13": "gbc",
"14": "gym",
"15": "gyc",
"16": "gmc",
"17": "bym",
"18": "byc",
"19": "bmc",
"20": "ymc",
}
# Define Funcions
def take_image_picamera_opencv(shutter_speed, iso, resolution, led_rgb_value):
colour_string = led_rgb_value
color_substring_list = [str(x).zfill(2) for x in range(1,21)] # string list to check for color pattern
# Initialise Camera
with picamera.PiCamera() as camera:
with PiRGBArray(camera) as output:
# Set camera settings
camera.sensor_mode = SENSOR_MODE # force camera into desired sensor mode
camera.resolution = resolution # frame will be resized from GPU to this resolution. No CPU usage!
camera.framerate = FRAMERATE
camera.awb_mode = AWB_MODE
camera.awb_gains = AWB_GAINS
camera.iso = iso # Iso must be set prior fixing the gains (prior setting exposure_mode to off)
camera.shutter_speed = shutter_speed
# it was found that, you have to set the right shutter speed at the first initalisation of the current runtime of the program.
# The gains (analog, digital) will adjust to this set up.
# After the gains are fixed, they will never change! even if you change the shutter speed during the runtime.
# To get consistent brightness values, set the right shutter speed at initalisation once.
time.sleep(SLEEP_TIME) # wait for iso gains and digital_gain and analog_gain to settle before fixing the gains with exposure_mode = off
# digital_gain: The value represents the digital gain the camera applies after conversion of the sensors analog output.
# analog_gain: The value represents the analog gain of the sensor prior to digital conversion.
# digital and analog gain can not be set from the user.
camera.exposure_mode = EXPOSURE_MODE
# exposure_mode value 'off' overrides the ISO setting.
# For example, 'off' fixes analog_gain and digital_gain entirely,
# preventing this property from adjusting them when set.
time.sleep(1)
camera.brightness = BRIGHTNESS
camera.contrast = CONTRAST
# camera.start_preview()
time.sleep(SLEEP_TIME) # Camera warm-up time to apply settings
exposure_speed = camera.exposure_speed # settings have to be applied before retrieving the right exposure_speed
# cv.namedWindow("Current Frame", cv.WINDOW_NORMAL)
for frameidx, frame in enumerate(camera.capture_continuous(output, format='bgr', use_video_port=True)):
framenumber = frameidx+1 # frameidx starts with 0, framenumber with 1
image = frame.array # raw NumPy array without JPEG encoding
#display_image_with_text(image, shutter_speed, framenumber) # show the frame
framenumber_to_save = 15 # save frame 15 (no particular reason for frame 15)
if framenumber == framenumber_to_save: # save desired frame
now = datetime.now(); d1 = now.strftime("%Y-%m-%d %H-%M-%S")
print(f"Take picture! iso: {iso} shutter speed: {shutter_speed} µs")
if "-" in colour_string:
cv.imwrite(f"{path_saveFolder}/RGB {colour_string}_ss{shutter_speed}_es{exposure_speed}_iso{iso}_b{BRIGHTNESS}_c{CONTRAST}_res{resolution[0]}x{resolution[1]}_Date {d1}.png", image)
elif any(substring in colour_string for substring in color_substring_list):
cv.imwrite(f"{path_saveFolder}/cp {colour_string}-{dict_color_pattern[colour_string]}_ss{shutter_speed}_es{exposure_speed}_iso{iso}_b{BRIGHTNESS}_c{CONTRAST}_res{resolution[0]}x{resolution[1]}_Date {d1}.png", image)
break # break from the loop, because we took the image we wanted
output.truncate(0) # clear the stream for next frame
# Only uncomment following code if you display the image. No errors if not commented, but higher fps if commented.
# if q is pressed, break from loop.
# if cv.waitKey(1) & 0xff == ord('q'):
# break
def take_image_series_onecolourchannel_per_led(led_rgb_value):
"""Take image series in one specified colour."""
s.write(str.encode(led_rgb_value)); response = s.readline(); print(response)
for i, resolution in enumerate(camera_resolutions):
print(f'resolution {i+1}/{len(camera_resolutions)}: {resolution}')
for ss in shutter_speeds:
for iso in iso_values:
take_image_picamera_opencv(ss, iso, resolution, led_rgb_value)
def take_image_series_rgb(brightness):
"""Take image series. One colour per series."""
t1 = time.perf_counter()
print(f'switchting to red')
led_rgb_value = f"{brightness}-000-000"
s.write(str.encode(led_rgb_value)); response = s.readline(); print(response)
for i, resolution in enumerate(camera_resolutions):
print(f'resolution {i+1}/{len(camera_resolutions)}: {resolution}')
for ss in shutter_speeds:
for iso in iso_values:
take_image_picamera_opencv(ss, iso, resolution, led_rgb_value)
print('switchting to green')
led_rgb_value = f"000-{brightness}-000"
s.write(str.encode(led_rgb_value)); response = s.readline(); print(response)
for i, resolution in enumerate(camera_resolutions):
print(f'resolution {i+1}/{len(camera_resolutions)}: {resolution}')
for ss in shutter_speeds:
for iso in iso_values:
take_image_picamera_opencv(ss, iso, resolution, led_rgb_value)
print('switchting to blue')
led_rgb_value = f"000-000-{brightness}"
s.write(str.encode(led_rgb_value)); response = s.readline(); print(response)
for i, resolution in enumerate(camera_resolutions):
print(f'resolution {i+1}/{len(camera_resolutions)}: {resolution}')
for ss in shutter_speeds:
for iso in iso_values:
take_image_picamera_opencv(ss, iso, resolution, led_rgb_value)
t2 = time.perf_counter()
elapsed_time = round((t2-t1)/60,2)
print(f'series_rgb finished in {elapsed_time} min')
def take_image_series_ymc(brightness):
"""Take image series. One colour per series."""
t1 = time.perf_counter()
print(f'switchting to yellow')
led_rgb_value = f"{brightness}-{brightness}-000"
s.write(str.encode(led_rgb_value)); response = s.readline(); print(response)
for i, resolution in enumerate(camera_resolutions):
print(f'resolution {i+1}/{len(camera_resolutions)}: {resolution}')
for ss in shutter_speeds:
for iso in iso_values:
take_image_picamera_opencv(ss, iso, resolution, led_rgb_value)
print('switchting to magenta')
led_rgb_value = f"{brightness}-000-{brightness}"
s.write(str.encode(led_rgb_value)); response = s.readline(); print(response)
for i, resolution in enumerate(camera_resolutions):
print(f'resolution {i+1}/{len(camera_resolutions)}: {resolution}')
for ss in shutter_speeds:
for iso in iso_values:
take_image_picamera_opencv(ss, iso, resolution, led_rgb_value)
print('switchting to cyan')
led_rgb_value = f"000-{brightness}-{brightness}"
s.write(str.encode(led_rgb_value)); response = s.readline(); print(response)
for i, resolution in enumerate(camera_resolutions):
print(f'resolution {i+1}/{len(camera_resolutions)}: {resolution}')
for ss in shutter_speeds:
for iso in iso_values:
take_image_picamera_opencv(ss, iso, resolution, led_rgb_value)
t2 = time.perf_counter()
elapsed_time = round((t2-t1)/60,2)
print(f'series_rgb finished in {elapsed_time} min')
def take_image_series_twocolourchannels_per_led(brightness):
"""Take image series. Two colours per series."""
# All posibilities with R G B: RG, RB, GB
print(f'switchting to red and green')
led_rgb_value = f"{brightness}-{brightness}-000"
s.write(str.encode(led_rgb_value)); response = s.readline(); print(response)
for ss in range(START_SHUTTER_SPEED, END_SHUTTER_SPEED+STEP_SHUTTER_SPEED, STEP_SHUTTER_SPEED):
take_image_picamera_opencv(ss, led_rgb_value)
print('switchting to red and blue')
led_rgb_value = f"{brightness}-000-{brightness}"
s.write(str.encode(led_rgb_value)); response = s.readline(); print(response)
for ss in range(START_SHUTTER_SPEED, END_SHUTTER_SPEED+STEP_SHUTTER_SPEED, STEP_SHUTTER_SPEED):
take_image_picamera_opencv(ss, led_rgb_value)
print('switchting to green and blue')
led_rgb_value = f"000-{brightness}-{brightness}"
s.write(str.encode(led_rgb_value)); response = s.readline(); print(response)
for ss in range(START_SHUTTER_SPEED, END_SHUTTER_SPEED+STEP_SHUTTER_SPEED, STEP_SHUTTER_SPEED):
take_image_picamera_opencv(ss, led_rgb_value)
def takeimage_all_color_patterns():
"""Take images of all 20 color patterns including orientation """
"The brightness is hard coded to 255 in the Arduino"
t1 = time.perf_counter()
print(f'take images for all 20 color patterns')
for number_of_color_pattern in range(1,21):
number_of_color_pattern = str(number_of_color_pattern).zfill(2)
print(f"color pattern no: {number_of_color_pattern}: {dict_color_pattern[number_of_color_pattern]}")
s.write(str.encode(f"color_pattern_{number_of_color_pattern}"))
for i, resolution in enumerate(camera_resolutions):
print(f'resolution {i+1}/{len(camera_resolutions)}: {resolution}')
for ss in shutter_speeds:
for iso in iso_values:
take_image_picamera_opencv(ss, iso, resolution, number_of_color_pattern)
t2 = time.perf_counter()
elapsed_time = round((t2-t1)/60,2)
print(f'series_rgb finished in {elapsed_time} min')
def display_image_with_text(img, shutter_speed, framenumber):
img = img.copy() # make copy of image and do not modify the original image
font = cv.FONT_HERSHEY_SIMPLEX # font
fontScale = 1 # fontScale
color = (255, 255, 255) # Font colour in BGR
thickness = 1 # Line thickness in px
# set text position
frame_width = int(img.shape[1])
frame_height = int(img.shape[0])
text_start_position_Y = int(round(frame_height*0.12)) # start position of text in pixels 12 % of frame height
text_linespacing = 50 # line spacing between two strings in pixels
# set position in (x,y)-coordinated from top left corner. Bottom-left corner of the text string in the image.
pos_1 = (int(frame_width/4), text_start_position_Y) # start text from 1/4 of image width
pos_2 = (int(frame_width/4), text_start_position_Y+text_linespacing) # start text from 1/4 of image width
# define text to display
text_line_1 = f"Shutterspeed: {shutter_speed} us"
text_line_2 = f"Frame: {framenumber}"
# put the text into the image
image_text_1 = cv.putText(img, text_line_1, pos_1, font,
fontScale, color, thickness, cv.LINE_AA)
image_text_2 = cv.putText(img, text_line_2, pos_2, font,
fontScale, color, thickness, cv.LINE_AA)
cv.imshow("Current Frame", img) # display the image
# Start Script
# Create folder for saving the captured pictures
now = datetime.now(); d1 = now.strftime("%Y-%m-%d %H-%M")
path_cwd = os.getcwd()
# path_saveFolder = path_cwd+r"/Solarradiation_"+d1
path_saveFolder = path_cwd+r"/series_"+d1
try:
os.mkdir(path_saveFolder)
lines = [f"CAMERA NR: {CAM_NR}", f"CAMERA DESCRIPTION: {CAM_DESCRIPTION}", f"CAMERA EAN: {CAM_EAN}",
f"\n#Camera settings:", f"SENSOR MODE: {SENSOR_MODE}",
f"FRAMERATE: {FRAMERATE} # frames per second",
f"AWB_MODE: {AWB_MODE}", f"AWB_GAINS (red, blue): {AWB_GAINS}",
f"Brightness: {BRIGHTNESS}", f"Contrast: {CONTRAST}",
f"EXPOSURE_MODE: {EXPOSURE_MODE}",
f"\nCOMMENT: {COMMENT}"]
with open(os.path.join(path_saveFolder, "log.txt"), "w") as f:
f.write("\n".join(lines))
except OSError:
print("Error! Ending script. Try it again in 1 minute")
quit()
# Turn on LEDs
s = serial.Serial("/dev/ttyACM0", 9600) # Name of USB-Port may vary (here: ACM0)
time.sleep(5) # der Arduino resettet nach einer Seriellen Verbindung, daher muss kurz gewartet werden
# start capture series for different shutter speeds
print('start caputure series...')
# s.write(str.encode("000-255-000")); response = s.readline(); print(response)
# take_image_picamera_opencv(shutter_speed=200, led_rgb_value="000-255-000")
# take image series for two colour channels per led
# for brgns in range(50,260,50):
# brgns=str(brgns).zfill(3)
# take_image_series_twocolourchannels_per_led(brgns) #Take Image Series for every color in given brightness
# take_image_series_twocolourchannels_per_led(255) #Take Image Series for every color in given brightness
# # take image series for white colour
# for brgns in range(50,260,50):
# brgns=f"{brgns}".zfill(3)
# ledcolour=f"{brgns}-{brgns}-{brgns}"
# take_image_series_onecolourchannel_per_led(ledcolour)
# take_image_series_onecolourchannel_per_led("255-255-255")
# --------------------------------------------------------------------------------------------------------------------------------------------
# # 03.02.2022: Take images with multiple shutter speeds but in brightness 255 for determining colour falsification to the edges of the image
# take_image_series_rgb(255)
# take_image_series_ymc(255)
# take_image_series_onecolourchannel_per_led("255-255-255")
# --------------------------------------------------------------------------------------------------------------------------------------------
# # 26.02.2022: Take images with multiple shutter speeds and brightness for investigating the influence of the solar radiation on the images
# # take image series for rgb
# for brgns in range(50,260,50):
# brgns=str(brgns).zfill(3)
# take_image_series_ymc(brgns) #Take Image Series for every color in given brightness
# take_image_series_ymc(255) #Take Image Series for every color in given brightness
# # take image series for ymc
# for brgns in range(50,260,50):
# brgns=str(brgns).zfill(3)
# take_image_series_rgb(brgns) #Take Image Series for every color in given brightness
# take_image_series_rgb(255) #Take Image Series for every color in given brightness
# # take image series for white colour
# for brgns in range(50,260,50):
# brgns=f"{brgns}".zfill(3)
# ledcolour=f"{brgns}-{brgns}-{brgns}"
# take_image_series_onecolourchannel_per_led(ledcolour)
# take_image_series_onecolourchannel_per_led("255-255-255")
# --------------------------------------------------------------------------------------------------------------------------------------------
# 10.04.2022: Take images with multiple shutter speeds for investigating the influence of the solar radiation on the images
# take image series for rgb
take_image_series_rgb(255) #Take Image Series for every color in given brightness
# take image series for ymc
take_image_series_ymc(255) #Take Image Series for every color in given brightness
# take image series for white colour
take_image_series_onecolourchannel_per_led("255-255-255")
# --------------------------------------------------------------------------------------------------------------------------------------------
# 07.03.2022: Take images of all 20 color patterns with birghtness 255
takeimage_all_color_patterns()
# --------------------------------------------------------------------------------------------------------------------------------------------
# End Script
# Turn off LEDs
s.write(str.encode('000-000-000')); response = s.readline(); print(response)
s.close() #close serial port
cv.destroyAllWindows()
t1 = round(time.perf_counter()/60,2)
print(f'Script finished in {t1} min')