SA-Kenan/03_Aufnahmeserie/Takeimage_Shutterspeed_PiCameraVideoPort_V01-02.py
2022-05-09 20:30:26 +02:00

442 lines
20 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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