# Date: 18.12.2021 # Author: Kenan Gömek # Das Skript stellt die unterschiedlichen Farbkanäle der aufgenommenen Bilder dar und erstellt schnitte, um die Pixelwerte anzuzeigen. # Update:21.12.2021 # Update Comment: Dominierender Farbkanal wird automatisch erkannt und die Zeilen- und Spaltenmarkierungen werden alle nach dem hellsten # Punkt im dominierenden Farbkanal gerichtet # Import needed Packages import cv2 as cv import numpy as np import time from datetime import datetime import os from matplotlib import pyplot as plt # define User Input # No vowels in path name!' PATH_IMAGE_FOLDER = r'U:\bwsyncshare\Auswertung' COMMENT = "" # User Comment for plot # select cut mode for determining pixel values cut_mode = 'auto' # options: 'auto', 'manual' ROW = 152 # Row-Number for Cut [Pixels] for cut_mode 'manual' index begins from 0 COLUMN = 1742 # Column-Number for Cut [Pixels] for cut_mode 'manual' index begins from 0 # define functions def calc_arithmetic_mean_of_brightness_per_pixel(r, g, b): """Calculate overall brightness per pixel of the image. Mittelere Helligkeit pro pixel berechnen.""" r = r.astype('uint16') # set dtype of one colour to uint16, because the sum of 255+255+255 >255 =765 # the rest will also be uint16 then image_heigth = r.shape[0] image_width = r.shape[1] number_of_colour_channels = 3 arithmetic_mean_of_brightness_image = np.sum((r+g+b)/number_of_colour_channels) arithmetic_mean_of_brightness_per_pixel = arithmetic_mean_of_brightness_image/(image_width*image_heigth) max_possible_brightness = 255 # maximum possible brightness for an uint8 arithmetic_mean_of_brightness_per_pixel_relative = arithmetic_mean_of_brightness_per_pixel/max_possible_brightness # range: 0-1 return arithmetic_mean_of_brightness_per_pixel_relative # start image_filenames = [f for f in os.listdir(PATH_IMAGE_FOLDER) if f.endswith('.png')] image_filenames.sort() for image_number, image_name in enumerate(image_filenames): print(f"Current image {image_number+1}/{len(image_filenames)}: {image_name}") # Split and Merge colour channels img_bgr = cv.imread(os.path.join(PATH_IMAGE_FOLDER,image_name), cv.IMREAD_COLOR) b, g, r = cv.split(img_bgr) img_rgb = img_bgr[:, :, ::-1] # Create Cuts and display Pixel Values image_width = r.shape[1] if image_width < 1000: plot_marker_offset = 4 # Thickness of marker-line in plot in pixels elif image_width >= 1000: plot_marker_offset = 10 # Thickness of marker-line in plot in pixels # Identify dominating colour channel and set cut row and column max_pixelvalue_red = r.max(); max_pixelvalue_green = g.max(); max_pixelvalue_blue = b.max() max_pixelvalue = np.max([max_pixelvalue_red, max_pixelvalue_green, max_pixelvalue_blue]) idx_max_pixelvalue_red = np.unravel_index(r.argmax(), r.shape) # row=idx_..[0] column=idx_..[1] idx_max_pixelvalue_green = np.unravel_index(g.argmax(), g.shape) # row=idx_..[0] column=idx_..[1] idx_max_pixelvalue_blue = np.unravel_index(b.argmax(), b.shape) # row=idx_..[0] column=idx_..[1] if max_pixelvalue == max_pixelvalue_red: idx_max_pixelvalue = idx_max_pixelvalue_red; msg_dominating_colourchannel = 'red' elif max_pixelvalue == max_pixelvalue_green: idx_max_pixelvalue = idx_max_pixelvalue_green; msg_dominating_colourchannel = 'green' elif max_pixelvalue == max_pixelvalue_blue: idx_max_pixelvalue = idx_max_pixelvalue_blue; msg_dominating_colourchannel = 'blue' if cut_mode == 'auto': cut_row = idx_max_pixelvalue[0]; cut_column = idx_max_pixelvalue[1] elif cut_mode == 'manual': cut_row = ROW; cut_column = COLUMN else: print('Wrong cut_mode. End script.'); quit() # Red channel # Info linspace(start, stop, num): # stop: The end value of the sequence --> stop is included # num: Number of samples to generate. # Because Array stars at index 0: e.g. image with 3280x2464 Pixels: for 3280 Pixels you need 3280 values between 0 and 3279 # check: x_red_h must have 3280 values?? --> Yes from 0 to 3279 in 1 steps x_red_h = np.linspace(0, r.shape[1]-1, r.shape[1]); y_red_h = r[cut_row,:] # data horizontal cut ->width (e.g.: 3280) x_red_v = np.linspace(0, r.shape[0]-1, r.shape[0]); y_red_v = r[:,cut_column] # data vertical cut ->height (e.g.: 2464) msg1_red = f"Maximum Pixel value in red channel: {max_pixelvalue_red}"; print(msg1_red) msg2_red = f"Index of max Value in red channel (row, colum): {idx_max_pixelvalue_red}"; print(msg2_red) msg3_red = f"Maximum Pixel value in marked-row {cut_row}: {np.max(y_red_h)}"; print(msg3_red) msg4_red = f"Maximum Pixel value in marked-column {cut_column}: {np.max(y_red_v)}"; print(msg4_red) r_copy = r.copy(); r_copy[cut_row:cut_row+plot_marker_offset,:]=255; r_copy[:, cut_column:cut_column+plot_marker_offset]=255 # manipulate image for displaying in marked plot # Green channel x_green_h = np.linspace(0, g.shape[1]-1, g.shape[1]); y_green_h = g[cut_row,:] # data horizontal cut x_green_v = np.linspace(0, g.shape[0]-1, g.shape[0]); y_green_v = g[:,cut_column] # data vertical cut msg1_green = f"Maximum Pixel value in green channel: {max_pixelvalue_green}"; print(msg1_green) msg2_green = f"Index of max Value in green channel (row, colum): {idx_max_pixelvalue_green}"; print(msg2_green) msg3_green = f"Maximum Pixel value in marked-row {cut_row}: {np.max(y_green_h)}"; print(msg3_green) msg4_green = f"Maximum Pixel value in marked-column {cut_column}: {np.max(y_green_v)}"; print(msg4_green) g_copy = g.copy(); g_copy[cut_row:cut_row+plot_marker_offset,:]=255; g_copy[:, cut_column:cut_column+plot_marker_offset]=255 # manipulate image for displaying in marked plot # Blue channel x_blue_h = np.linspace(0, b.shape[1]-1, b.shape[1]); y_blue_h = b[cut_row,:] # data horizontal cut x_blue_v = np.linspace(0, b.shape[0]-1, b.shape[0]); y_blue_v = b[:,cut_column] # data vertical cut msg1_blue = f"Maximum Pixel value in blue channel: {max_pixelvalue_blue}"; print(msg1_blue) msg2_blue = f"Index of max Value in blue channel (row, colum): {idx_max_pixelvalue_blue}"; print(msg2_blue) msg3_blue = f"Maximum Pixel value in marked-row {cut_row}: {np.max(y_blue_h)}"; print(msg3_blue) msg4_blue = f"Maximum Pixel value in marked-column {cut_column}: {np.max(y_blue_v)}"; print(msg4_blue) b_copy = b.copy(); b_copy[cut_row:cut_row+plot_marker_offset,:]=255; b_copy[:, cut_column:cut_column+plot_marker_offset]=255 # manipulate image for displaying in marked plot # Create Plots fig1, ((ax_orig_1,ax01,ax02,ax03),(ax_red_1, ax_red_2, ax_red_3, ax_red_4), (ax_green_1, ax_green_2, ax_green_3, ax_green_4),(ax_blue_1, ax_blue_2, ax_blue_3, ax_blue_4)) \ = plt.subplots(4, 4, figsize=(30,25)) fig1.suptitle(f'Image: {image_name}', y=0.9) yticks=np.append(np.arange(0,230,25), 255) #set yticks for cuts xlim_max_h=r.shape[1] # xlim for horizontal cut. No special reason for choosing red channel. xlim_max_v=r.shape[0] # xlim for vertical cut. No special reason for choosing red channel. ax_orig_1.imshow(img_rgb); ax_orig_1.set_title("Original Image"); ax_orig_1.set_xlabel('Width=H=Columns'); ax_orig_1.set_ylabel('Heigth=V=Rows') # red channel ax_red_1.imshow(r, cmap = 'gray'); ax_red_1.set_title("Red Channel"); ax_red_1.set_xlabel('Width=H=Columns'); ax_red_1.set_ylabel('Heigth=V=Rows') ax_red_2.imshow(r_copy, cmap = 'gray'); ax_red_2.set_title("Red Channel - marked"); ax_red_2.set_xlabel('Width=H=Columns'); ax_red_2.set_ylabel('Heigth=V=Rows') ax_red_3.plot(x_red_h,y_red_h, linewidth=2.0); ax_red_3.set_title("Horizontal Cut"); ax_red_3.grid(True); ax_red_3.set_ylim(ymin=0, ymax=260); ax_red_3.set_yticks(yticks); ax_red_3.set_xlim(0,xlim_max_h) ax_red_3.set_xlabel('Width=H=Columns'); ax_red_3.set_ylabel('Pixel Value') ax_red_4.plot(x_red_v,y_red_v, linewidth=2.0); ax_red_4.set_title("Vertical Cut"); ax_red_4.grid(True); ax_red_4.set_ylim(ymin=0, ymax=260); ax_red_4.set_yticks(yticks); ax_red_4.set_xlim(0, xlim_max_v) ax_red_4.set_xlabel('Heigth=V=Rows'); ax_red_4.set_ylabel('Pixel Value') # green channel ax_green_1.imshow(g, cmap = 'gray'); ax_green_1.set_title("Green Channel"); ax_green_1.set_xlabel('Width=H=Columns'); ax_green_1.set_ylabel('Heigth=V=Rows') ax_green_2.imshow(g_copy, cmap = 'gray'); ax_green_2.set_title("Green Channel - marked"); ax_green_2.set_xlabel('Width=H=Columns'); ax_green_2.set_ylabel('Heigth=V=Rows') ax_green_3.plot(x_green_h,y_green_h, linewidth=2.0); ax_green_3.set_title("Horizontal Cut"); ax_green_3.grid(True); ax_green_3.set_ylim(ymin=0, ymax=260); ax_green_3.set_yticks(yticks); ax_green_3.set_xlim(0,xlim_max_h) ax_green_3.set_xlabel('Width=H=Columns'); ax_green_3.set_ylabel('Pixel Value') ax_green_4.plot(x_green_v,y_green_v, linewidth=2.0); ax_green_4.set_title("Vertical Cut"); ax_green_4.grid(True); ax_green_4.set_ylim(ymin=0, ymax=260); ax_green_4.set_yticks(yticks); ax_green_4.set_xlim(0, xlim_max_v) ax_green_4.set_xlabel('Heigth=V=Rows'); ax_green_4.set_ylabel('Pixel Value') # blue channel ax_blue_1.imshow(b, cmap = 'gray'); ax_blue_1.set_title("Blue Channel"); ax_blue_1.set_xlabel('Width=H=Columns'); ax_blue_1.set_ylabel('Heigth=V=Rows') ax_blue_2.imshow(b_copy, cmap = 'gray'); ax_blue_2.set_title("Blue Channel - marked"); ax_blue_2.set_xlabel('Width=H=Columns'); ax_blue_2.set_ylabel('Heigth=V=Rows') ax_blue_3.plot(x_blue_h,y_blue_h, linewidth=2.0); ax_blue_3.set_title("Horizontal Cut"); ax_blue_3.grid(True); ax_blue_3.set_ylim(ymin=0, ymax=260); ax_blue_3.set_yticks(yticks); ax_blue_3.set_xlim(0,xlim_max_h) ax_blue_3.set_xlabel('Width=H=Columns'); ax_blue_3.set_ylabel('Pixel Value') ax_blue_4.plot(x_blue_v,y_blue_v, linewidth=2.0); ax_blue_4.set_title("Vertical Cut"); ax_blue_4.grid(True); ax_blue_4.set_ylim(ymin=0, ymax=260); ax_blue_4.set_yticks(yticks); ax_blue_4.set_xlim(0, xlim_max_v) ax_blue_4.set_xlabel('Heigth=V=Rows'); ax_blue_4.set_ylabel('Pixel Value') # Calculate overall brightness per pixel of the image. Mittelere Helligkeit pro pixel berechnen. arithmetic_mean_of_brightness_per_pixel_relative = calc_arithmetic_mean_of_brightness_per_pixel(r,g,b) if arithmetic_mean_of_brightness_per_pixel_relative >= 0.01: msg1_brightness = f"Overall brightness per pixel: {round(arithmetic_mean_of_brightness_per_pixel_relative*100,2)} %" #value in percent elif arithmetic_mean_of_brightness_per_pixel_relative < 0.01: msg1_brightness = f"Overall brightness per pixel: {round(arithmetic_mean_of_brightness_per_pixel_relative*10e3,2)} per mil" # value in promille print(msg1_brightness) # add pixel stats under Figure pixelstats_red= '\n'.join([msg1_red, msg2_red, msg3_red, msg4_red]) pixelstats_green= '\n'.join([msg1_green, msg2_green, msg3_green, msg4_green]) pixelstats_blue= '\n'.join([msg1_blue, msg2_blue, msg3_blue, msg4_blue]) pixelstats_overall_brightness = '\n'.join([msg1_brightness]) pixelstats = '\n\n'.join([f"pixel stats: {msg_dominating_colourchannel} channel dominating", pixelstats_red, pixelstats_green, pixelstats_blue, pixelstats_overall_brightness]) text_x_pos = 0.1; text_y_pos = -0.015 # text position: 0,0 is lower-left and 1,1 is upper-right) fig1.text(text_x_pos, text_y_pos, pixelstats, ha='left') # add Comment under Figure text_x_pos = 0.5; text_y_pos = -0.025 # text position: 0,0 is lower-left and 1,1 is upper-right) log_filename=None try: log_filename=[f for f in os.listdir(PATH_IMAGE_FOLDER) if f.endswith('.txt')][0] if log_filename: with open(os.path.join(PATH_IMAGE_FOLDER,log_filename), encoding='utf-8') as f: log_text = f.readlines() if COMMENT != "": COMMENT = '\nPlot Comment: '+COMMENT log_text.append(COMMENT) txt=''.join(log_text) fig1.text(text_x_pos, text_y_pos, txt, ha='left') except IndexError: if COMMENT != "": COMMENT = '\nPlot Comment: '+COMMENT fig1.text(text_x_pos, text_y_pos, COMMENT, ha='left') else: pass # handle numpy memmory error on Windows: switch_overwrite=0 # do not overwrite files, if they exist if switch_overwrite == 1: fig1.savefig(os.path.join(PATH_IMAGE_FOLDER,f'{image_name}.pdf'), bbox_inches='tight') #save plot print('Save pdf') else: if os.path.isfile(os.path.join(PATH_IMAGE_FOLDER,f'{image_name}.pdf')): pass # skip this pdf file, because it already exists else: fig1.savefig(os.path.join(PATH_IMAGE_FOLDER,f'{image_name}.pdf'), bbox_inches='tight') #save plot print('Save pdf') plt.close('all') # close all figures print('') # new line for better readability in console