face01lib.Calc のソースコード

"""A module that performs various calculations.

Calculation results are output to log
"""
from datetime import datetime
from functools import wraps
from time import perf_counter
from typing import Tuple

import numpy as np
import numpy.typing as npt
from PIL import Image, ImageDraw, ImageFile, ImageFont
from scipy.optimize import fsolve

from face01lib.logger import Logger

ImageFile.LOAD_TRUNCATED_IMAGES = True


[ドキュメント] class Cal: """Cal class include various calculation methods.""" HANDLING_FRAME_TIME: float HANDLING_FRAME_TIME_FRONT: float HANDLING_FRAME_TIME_REAR: float x1: int y1: int x2: int y2: int def __init__(self, log_level: str = 'info') -> None: """init. Args: log_level (str, optional): Receive log level value. Defaults to 'info'. """ # Setup logger: common way self.log_level: str = log_level import os.path name: str = __name__ dir: str = os.path.dirname(__file__) parent_dir, _ = os.path.split(dir) self.logger = Logger(self.log_level).logger(name, parent_dir)
[ドキュメント] @staticmethod def Measure_processing_time( HANDLING_FRAME_TIME_FRONT, HANDLING_FRAME_TIME_REAR ) -> float: """Measurement of processing time (calculation) and output to log. Args: HANDLING_FRAME_TIME_FRONT (float): First half point HANDLING_FRAME_TIME_REAR (float): Second half point """ HANDLING_FRAME_TIME = \ (HANDLING_FRAME_TIME_REAR - HANDLING_FRAME_TIME_FRONT) # 小数点以下がミリ秒 # logger.info(f'Processing time: {round(HANDLING_FRAME_TIME, 3)}[Sec]') return HANDLING_FRAME_TIME
[ドキュメント] @staticmethod def Measure_processing_time_forward() -> float: """Measurement of processing time (first half). Returns: float: First half point """ HANDLING_FRAME_TIME_FRONT = perf_counter() return HANDLING_FRAME_TIME_FRONT
[ドキュメント] @staticmethod def Measure_processing_time_backward() -> float: """Measurement of processing time (second half). Returns: float: Second half point """ HANDLING_FRAME_TIME_REAR: float = perf_counter() return HANDLING_FRAME_TIME_REAR
[ドキュメント] def Measure_func(self, func): """Used as a decorator to time a function.""" self.func = func @wraps(self.func) def wrapper(*args, **kargs): start: float = perf_counter() result = func(*args, **kargs) elapsed_time: float = round((perf_counter() - start) * 1000, 2) print(f"{func.__name__}.............{elapsed_time}[mSec]") return result return wrapper
[ドキュメント] def cal_specify_date(self, logger) -> None: """終了期間を指定します Summary: プログラム使用制限を日付で指定します 呼び出されるモジュール内にこのメソッドを呼び出すことで、モジュールを使用不可にします。 アプリケーションを期限付きで運用する場合に有用です。 .. image:: ../assets/images/one_point_L.png :width: 70% :alt: one point このメソッドを使用する場合は'Cython'でバイナリ化しておくと良いですね⭐️'' """ self.logger = logger limit_date = datetime(2100, 12, 1, 0, 0, 0) # 指定日付 today = datetime.now() if today >= limit_date: self.logger.warning("Trial period expired") self.logger.warning("If you wish to continue using FACE01, please contact us.") self.logger.warning("email: y.kesamaru@tokai-kaoninsho.com") exit(0) elif today < limit_date: remaining_days = limit_date - today if remaining_days.days < 30: self.logger.info("Remaining days of use: ", str(remaining_days.days)) self.logger.warning( "If you wish to continue using FACE01, please contact us.") self.logger.warning("email: y.kesamaru@tokai-kaoninsho.com")
[ドキュメント] def cal_resized_telop_image( self, resized_telop_image: npt.NDArray[np.float64] ) -> Tuple[int, int, int, int, npt.NDArray[np.float64], npt.NDArray[np.float64]]: """Calculate telop image data. Args: resized_telop_image (npt.NDArray[np.float64]): Resized telop image data Returns: Tuple[int,int,int,int,npt.NDArray[np.float64],npt.NDArray[np.float64]]: Tuple Example: >>> cal_resized_telop_nums = Cal().cal_resized_telop_image(resized_telop_image) """ self.resized_telop_image = resized_telop_image x1, y1, x2, y2 = 0, 0, resized_telop_image.shape[1], resized_telop_image.shape[0] a = (1 - resized_telop_image[:, :, 3:] / 255) b = resized_telop_image[:, :, :3] * \ (resized_telop_image[:, :, 3:] / 255) cal_resized_telop_nums = (x1, y1, x2, y2, a, b) return cal_resized_telop_nums
[ドキュメント] def cal_resized_logo_image( self, resized_logo_image: npt.NDArray[np.float64], set_height: int, set_width: int ) -> Tuple[int, int, int, int, npt.NDArray[np.float64], npt.NDArray[np.float64]]: """Calculate logo image data. Args: resized_logo_image (npt.NDArray[np.float64]): Resized logo image data set_height (int): Height set_width (int): Width Returns: Tuple[int,int,int,int,npt.NDArray[np.float64],npt.NDArray[np.float64]]: Return tuple Example: >>> cal_resized_logo_nums = Cal().cal_resized_logo_image( resized_logo_image, set_height, set_width ) """ self.resized_logo_image: npt.NDArray[np.float64] = resized_logo_image self.set_height: int = set_height self.set_width: int = set_width x1, y1, x2, y2 = set_width - \ resized_logo_image.shape[1], set_height - \ resized_logo_image.shape[0], set_width, set_height a = (1 - resized_logo_image[:, :, 3:] / 255) b = resized_logo_image[:, :, :3] * (resized_logo_image[:, :, 3:] / 255) cal_resized_logo_nums: Tuple[int, int, int, int, npt.NDArray[np.float64], npt.NDArray[np.float64]] = \ (x1, y1, x2, y2, a, b) return cal_resized_logo_nums
[ドキュメント] def to_tolerance( self, similar_percentage: float, deep_learning_model: int, ) -> float: """similar_percentageを受け取ってtoleranceを返します. Args: similar_percentage (float): config.iniで設定されたProbability of similarityの値 deep_learning_model (int): Deep learning modelを選びます. Returns: float: tolerance Note: deep_learning_model: 0:dlib_face_recognition_resnet_model_v1.dat, 1:JAPANESE_FACE_V1.onnx, 2:mobilefacenet.onnx Example: >>> tolerance: float = Cal().to_tolerance( self.CONFIG["similar_percentage"], self.CONFIG["deep_learning_model"] ) Dlib ## 算出式 ## percentage = -4.76190475*(p*p)+(-0.380952375)*p+100 ## percentage_example = -4.76190475*(0.45*0.45)+(-0.380952375)*0.45+100 ## -4.76190475*(p*p)+(-0.380952375)*p+(100-similar_percentage) = 0 # 式の変更: 2023年9月14日 # # f(x) = 100 / (1 + exp(-10(x - 0.8))) # similar_percentage = 100 / (1 + np.exp(-10*(tolerance - 0.8))) JAPANESE_FACE_V1 ## 算出式 ## y=-23.71x2+49.98x+73.69 ## See: https://zenn.dev/ykesamaru/articles/bc74ec27925896#%E9%96%BE%E5%80%A4%E3%81%A8%E7%99%BE%E5%88%86%E7%8E%87 ## percentage = -23.71*(p*p)+49.98*p+73.69 ## 0 = -23.71*(p*p)+49.98*p+(73.69-similar_percentage) """ self.similar_percentage: float = similar_percentage tolerance: float = 0.0 if deep_learning_model == 0: # 旧式 ######################################### # tolerance_plus: float = (-1 * (-0.380952375) + np.sqrt((-0.380952375) * (-0.380952375) - 4 * (-4.76190475) * (100 - self.similar_percentage))) / (2 * (-4.76190475)) # tolerance_minus: float = (-1 * (-0.380952375) - np.sqrt((-0.380952375) * (-0.380952375) - 4 * (-4.76190475) * (100 - self.similar_percentage))) / (2 * (-4.76190475)) # if -5 < tolerance_plus < 0: # tolerance = tolerance_plus # elif 0 < tolerance_minus < 5: # tolerance = tolerance_minus # # toleranceの絶対値を得る # tolerance = abs(tolerance) # return tolerance # ############################################## # 新式 ######################################### def equation(tolerance): return similar_percentage - 100 / (1 + np.exp(-10 * (tolerance - 0.8))) tolerance_solution = fsolve(equation, 0.5) return tolerance_solution[0] # ############################################## elif deep_learning_model == 1: tolerance_plus: float = (-1 * 49.98 + np.sqrt(49.98 * 49.98 - 4 * (-23.71) * (73.69 - self.similar_percentage))) / (2 * (-23.71)) tolerance_minus: float = (-1 * 49.98 - np.sqrt(49.98 * 49.98 - 4 * (-23.71) * (73.69 - self.similar_percentage))) / (2 * (-23.71)) if 0 < tolerance_plus < 1: tolerance = tolerance_plus elif 0 < tolerance_minus < 1: tolerance = tolerance_minus return tolerance
[ドキュメント] def to_percentage( self, tolerance: float, deep_learning_model: int, ) -> float: """Receive 'tolerance' and return 'percentage'. Args: tolerance (float): tolerance Returns: float: percentage """ percentage: float = 0.0 self.tolerance: float = tolerance if deep_learning_model == 0: percentage: float = -4.76190475*(self.tolerance ** 2)+(-0.380952375) * self.tolerance +100 elif deep_learning_model == 1: percentage: float = -23.71*(self.tolerance ** 2)+49.98*self.tolerance+73.69 return percentage
[ドキュメント] def decide_text_position( self, error_messg_rectangle_bottom, error_messg_rectangle_left, error_messg_rectangle_right, error_messg_rectangle_fontsize, error_messg_rectangle_messg ): """Not use.""" self.error_messg_rectangle_bottom = error_messg_rectangle_bottom self.error_messg_rectangle_left = error_messg_rectangle_left self.error_messg_rectangle_right = error_messg_rectangle_right self.error_messg_rectangle_fontsize = error_messg_rectangle_fontsize self.error_messg_rectangle_messg = error_messg_rectangle_messg error_messg_rectangle_center = int((self.error_messg_rectangle_left + self.error_messg_rectangle_right) / 2) error_messg_rectangle_chaCenter = int(len(self.error_messg_rectangle_messg) / 2) error_messg_rectangle_pos = error_messg_rectangle_center - (error_messg_rectangle_chaCenter * self.error_messg_rectangle_fontsize) - int(self.error_messg_rectangle_fontsize / 2) error_messg_rectangle_position = (error_messg_rectangle_pos + self.error_messg_rectangle_fontsize, self.error_messg_rectangle_bottom - (self.error_messg_rectangle_fontsize * 2)) return error_messg_rectangle_position
[ドキュメント] def make_error_messg_rectangle_font( self, fontpath: str, error_messg_rectangle_fontsize: str, encoding='utf-8' ): """Not use.""" self.fontpath = fontpath self.error_messg_rectangle_fontsize = error_messg_rectangle_fontsize error_messg_rectangle_font = ImageFont.truetype( self.fontpath, self.error_messg_rectangle_fontsize, encoding='utf-8') return error_messg_rectangle_font
[ドキュメント] def return_percentage( self, distance: float, deep_learning_model: int ) -> float: # python版 """Receive 'distance' and return percentage. Args: distance (float): distance deep_learning_model (int): deep_learning_model Returns: float: percentage NOTE: deep_learning_model: 0:dlib_face_recognition_resnet_model_v1.dat, 1:JAPANESE_FACE_V1.onnx, 2:mobilefacenet.onnx(実装未定) Example: >>> percentage = Cal().return_percentage(distance, deep_learning_model) """ percentage: float = 0.0 self.distance: float = distance if deep_learning_model == 0: percentage: float = -4.76190475 *(self.distance**2)-(0.380952375*self.distance)+100 elif deep_learning_model == 1: percentage: float = -23.71*(self.distance**2)+(49.98*self.distance)+73.69 return percentage
[ドキュメント] def pil_img_instance( self, frame: npt.NDArray[np.uint8] ): """Generate pil_img object. Args: frame (npt.NDArray[np.uint8]): Image data Returns: object: PIL object """ self.frame: npt.NDArray[np.uint8] = frame pil_img_obj = Image.fromarray(self.frame) return pil_img_obj
[ドキュメント] def make_draw_rgb_object( self, pil_img_obj_rgb ): """Generate object. Args: pil_img_obj_rgb (object): object Returns: object: object """ self.pil_img_obj_rgb = pil_img_obj_rgb draw_rgb = ImageDraw.Draw(self.pil_img_obj_rgb) return draw_rgb