From c296dabec6b2fa058013dd0c2485dad646582af6 Mon Sep 17 00:00:00 2001 From: huangziyi Date: Wed, 27 Dec 2023 17:24:52 +0800 Subject: [PATCH] update examples Signed-off-by: huangziyi --- share/qtcreator/examples/01-Media/acodec.py | 187 +- share/qtcreator/examples/01-Media/audio.py | 143 +- share/qtcreator/examples/01-Media/camera.py | 150 +- .../examples/01-Media/camera_480p.py | 69 + share/qtcreator/examples/01-Media/display.py | 100 +- share/qtcreator/examples/01-Media/media.py | 85 +- share/qtcreator/examples/01-Media/mp4muxer.py | 71 +- share/qtcreator/examples/01-Media/player.py | 62 +- share/qtcreator/examples/01-Media/venc.py | 142 +- .../qtcreator/examples/02-Machine/adc/adc.py | 10 +- .../qtcreator/examples/02-Machine/fft/fft.py | 16 +- .../examples/02-Machine/fpioa/fpioa.py | 6 +- .../examples/02-Machine/gpio/gpio.py | 17 +- .../qtcreator/examples/02-Machine/i2c/i2c.py | 41 +- .../qtcreator/examples/02-Machine/pwm/pwm.py | 11 +- .../qtcreator/examples/02-Machine/spi/spi.py | 35 + .../examples/02-Machine/timer/timer.py | 10 +- .../examples/02-Machine/uart/uart.py | 16 + .../qtcreator/examples/02-Machine/wdt/wdt.py | 16 +- .../examples/04-AI-Demo/face_detection.py | 52 +- .../examples/04-AI-Demo/face_landmark.py | 51 +- .../examples/04-AI-Demo/face_mesh.py | 54 +- .../examples/04-AI-Demo/face_parse.py | 51 +- .../examples/04-AI-Demo/face_pose.py | 51 +- .../examples/04-AI-Demo/face_recognition.py | 51 +- .../examples/04-AI-Demo/face_registration.py | 10 +- .../examples/04-AI-Demo/finger_guessing.py | 50 +- .../examples/04-AI-Demo/hand_detection.py | 48 +- .../04-AI-Demo/hand_keypoint_detection.py | 49 +- .../examples/04-AI-Demo/hand_recognition.py | 49 +- .../examples/04-AI-Demo/keyword_spotting.py | 15 +- .../examples/04-AI-Demo/licence_det.py | 52 +- .../examples/04-AI-Demo/licence_det_rec.py | 52 +- .../04-AI-Demo/object_detect_yolov8n.py | 50 +- .../qtcreator/examples/04-AI-Demo/ocr_det.py | 51 +- .../qtcreator/examples/04-AI-Demo/ocr_rec.py | 49 +- .../examples/04-AI-Demo/person_detection.py | 50 +- .../examples/04-AI-Demo/person_kp_detect.py | 50 +- .../examples/04-AI-Demo/segment_yolov8n.py | 48 +- .../examples/05-nncase-Runtime/ai2d+kpu.py | 36 +- .../examples/05-nncase-Runtime/kpu.py | 27 +- .../examples/07-April-Tags/find_apriltags.py | 148 + .../07-April-Tags/find_apriltags_3d_pose.py | 148 + .../examples/08-Codes/find_barcodes.py | 150 + .../examples/08-Codes/find_datamatrices.py | 116 + .../examples/08-Codes/find_qrcodes.py | 115 + .../automatic_grayscale_color_tracking.py | 145 + .../automatic_rgb565_color_tracking.py | 149 + .../black_grayscale_line_following.py | 171 + .../09-Color-Tracking/image_histogram_info.py | 106 + .../image_statistics_info.py | 106 + .../multi_color_code_tracking.py | 141 + .../single_color_code_tracking.py | 135 + .../examples/10-Drawing/arrow_drawing.py | 105 + .../examples/10-Drawing/circle_drawing.py | 104 + .../examples/10-Drawing/cross_drawing.py | 103 + .../examples/10-Drawing/ellipse_drawing.py | 107 + .../examples/10-Drawing/flood_fill.py | 103 + .../examples/10-Drawing/image_drawing.py | 110 + .../10-Drawing/image_drawing_advanced.py | 183 + .../image_drawing_alpha_blending_test.py | 155 + .../examples/10-Drawing/keypoints_drawing.py | 104 + .../examples/10-Drawing/line_drawing.py | 105 + .../examples/10-Drawing/rectangle_drawing.py | 105 + .../examples/10-Drawing/text_drawing.py | 106 + .../examples/11-Feature-Detection/edges.py | 111 + .../11-Feature-Detection/find_circles.py | 131 + .../11-Feature-Detection/find_lines.py | 146 + .../11-Feature-Detection/find_rects.py | 123 + .../examples/11-Feature-Detection/hog.py | 111 + .../11-Feature-Detection/keypoints.py | 145 + .../examples/11-Feature-Detection/lbp.py | 144 + .../linear_regression_fast.py | 130 + .../linear_regression_robust.py | 132 + .../11-Feature-Detection/template_matching.py | 134 + .../adaptive_histogram_equalization.py | 118 + .../examples/12-Image-Filters/blur_filter.py | 109 + .../12-Image-Filters/cartoon_filter.py | 119 + .../color_bilateral_filter.py | 121 + .../12-Image-Filters/color_binary_filter.py | 135 + .../12-Image-Filters/color_light_removal.py | 115 + .../examples/12-Image-Filters/edge_filter.py | 109 + .../12-Image-Filters/erode_and_dilate.py | 136 + .../12-Image-Filters/gamma_correction.py | 111 + .../grayscale_bilateral_filter.py | 122 + .../grayscale_binary_filter.py | 127 + .../grayscale_light_removal.py | 115 + .../histogram_equalization.py | 109 + .../12-Image-Filters/kernel_filters.py | 115 + .../12-Image-Filters/lens_correction.py | 111 + .../examples/12-Image-Filters/linear_polar.py | 111 + .../examples/12-Image-Filters/log_polar.py | 111 + .../mean_adaptive_threshold_filter.py | 113 + .../examples/12-Image-Filters/mean_filter.py | 113 + .../median_adaptive_threshold_filter.py | 115 + .../12-Image-Filters/median_filter.py | 115 + .../midpoint_adaptive_threshold_filter.py | 116 + .../12-Image-Filters/midpoint_filter.py | 115 + .../mode_adaptive_threshold_filter.py | 113 + .../examples/12-Image-Filters/mode_filter.py | 113 + .../examples/12-Image-Filters/negative.py | 109 + .../perspective_and_rotation_correction.py | 159 + .../perspective_correction.py | 129 + .../12-Image-Filters/rotation_correction.py | 138 + .../12-Image-Filters/sharpen_filter.py | 109 + .../12-Image-Filters/unsharp_filter.py | 109 + .../vflip_hmirror_transpose.py | 122 + .../examples/13-Snapshot/emboss_snapshot.py | 77 + .../examples/13-Snapshot/snapshot.py | 73 + .../examples/14-Socket/http_client.py | 39 + .../examples/14-Socket/http_server.py | 81 + share/qtcreator/examples/14-Socket/iperf3.py | 582 ++ .../examples/14-Socket/network_lan.py | 38 + .../examples/14-Socket/tcp_client.py | 41 + .../examples/14-Socket/tcp_server.py | 68 + .../examples/14-Socket/udp_clinet.py | 38 + .../examples/14-Socket/udp_server.py | 45 + .../qtcreator/examples/15-Utils/db/readme.txt | 1 + .../examples/15-Utils/db_img/id_1.jpg | Bin 0 -> 15136 bytes .../examples/15-Utils/db_img/id_2.png | Bin 0 -> 188132 bytes share/qtcreator/examples/15-Utils/dict.txt | 6549 +++++++++++++++++ share/qtcreator/examples/15-Utils/fist.bin | 1313 ++++ share/qtcreator/examples/15-Utils/five.bin | 999 +++ .../examples/15-Utils/prior_data_320.bin | Bin 0 -> 67200 bytes share/qtcreator/examples/15-Utils/shear.bin | 866 +++ share/qtcreator/examples/15-Utils/wozai.wav | Bin 0 -> 17678 bytes 126 files changed, 19919 insertions(+), 1183 deletions(-) mode change 100755 => 100644 share/qtcreator/examples/01-Media/acodec.py mode change 100755 => 100644 share/qtcreator/examples/01-Media/audio.py create mode 100644 share/qtcreator/examples/01-Media/camera_480p.py mode change 100755 => 100644 share/qtcreator/examples/01-Media/mp4muxer.py mode change 100755 => 100644 share/qtcreator/examples/01-Media/player.py mode change 100755 => 100644 share/qtcreator/examples/01-Media/venc.py mode change 100755 => 100644 share/qtcreator/examples/02-Machine/adc/adc.py mode change 100755 => 100644 share/qtcreator/examples/02-Machine/fft/fft.py mode change 100755 => 100644 share/qtcreator/examples/02-Machine/fpioa/fpioa.py mode change 100755 => 100644 share/qtcreator/examples/02-Machine/gpio/gpio.py mode change 100755 => 100644 share/qtcreator/examples/02-Machine/pwm/pwm.py create mode 100755 share/qtcreator/examples/02-Machine/spi/spi.py mode change 100755 => 100644 share/qtcreator/examples/02-Machine/timer/timer.py create mode 100644 share/qtcreator/examples/02-Machine/uart/uart.py mode change 100755 => 100644 share/qtcreator/examples/02-Machine/wdt/wdt.py mode change 100755 => 100644 share/qtcreator/examples/04-AI-Demo/face_detection.py mode change 100755 => 100644 share/qtcreator/examples/04-AI-Demo/face_landmark.py mode change 100755 => 100644 share/qtcreator/examples/04-AI-Demo/face_mesh.py mode change 100755 => 100644 share/qtcreator/examples/04-AI-Demo/face_parse.py mode change 100755 => 100644 share/qtcreator/examples/04-AI-Demo/face_pose.py mode change 100755 => 100644 share/qtcreator/examples/04-AI-Demo/face_recognition.py mode change 100755 => 100644 share/qtcreator/examples/04-AI-Demo/face_registration.py mode change 100755 => 100644 share/qtcreator/examples/04-AI-Demo/finger_guessing.py mode change 100755 => 100644 share/qtcreator/examples/04-AI-Demo/hand_detection.py mode change 100755 => 100644 share/qtcreator/examples/04-AI-Demo/hand_keypoint_detection.py mode change 100755 => 100644 share/qtcreator/examples/04-AI-Demo/hand_recognition.py mode change 100755 => 100644 share/qtcreator/examples/04-AI-Demo/keyword_spotting.py mode change 100755 => 100644 share/qtcreator/examples/04-AI-Demo/licence_det.py mode change 100755 => 100644 share/qtcreator/examples/04-AI-Demo/licence_det_rec.py mode change 100755 => 100644 share/qtcreator/examples/04-AI-Demo/object_detect_yolov8n.py mode change 100755 => 100644 share/qtcreator/examples/04-AI-Demo/ocr_det.py mode change 100755 => 100644 share/qtcreator/examples/04-AI-Demo/ocr_rec.py mode change 100755 => 100644 share/qtcreator/examples/04-AI-Demo/person_detection.py mode change 100755 => 100644 share/qtcreator/examples/04-AI-Demo/person_kp_detect.py mode change 100755 => 100644 share/qtcreator/examples/04-AI-Demo/segment_yolov8n.py mode change 100755 => 100644 share/qtcreator/examples/05-nncase-Runtime/ai2d+kpu.py mode change 100755 => 100644 share/qtcreator/examples/05-nncase-Runtime/kpu.py create mode 100644 share/qtcreator/examples/07-April-Tags/find_apriltags.py create mode 100644 share/qtcreator/examples/07-April-Tags/find_apriltags_3d_pose.py create mode 100644 share/qtcreator/examples/08-Codes/find_barcodes.py create mode 100644 share/qtcreator/examples/08-Codes/find_datamatrices.py create mode 100644 share/qtcreator/examples/08-Codes/find_qrcodes.py create mode 100644 share/qtcreator/examples/09-Color-Tracking/automatic_grayscale_color_tracking.py create mode 100644 share/qtcreator/examples/09-Color-Tracking/automatic_rgb565_color_tracking.py create mode 100644 share/qtcreator/examples/09-Color-Tracking/black_grayscale_line_following.py create mode 100644 share/qtcreator/examples/09-Color-Tracking/image_histogram_info.py create mode 100644 share/qtcreator/examples/09-Color-Tracking/image_statistics_info.py create mode 100644 share/qtcreator/examples/09-Color-Tracking/multi_color_code_tracking.py create mode 100644 share/qtcreator/examples/09-Color-Tracking/single_color_code_tracking.py create mode 100644 share/qtcreator/examples/10-Drawing/arrow_drawing.py create mode 100644 share/qtcreator/examples/10-Drawing/circle_drawing.py create mode 100644 share/qtcreator/examples/10-Drawing/cross_drawing.py create mode 100644 share/qtcreator/examples/10-Drawing/ellipse_drawing.py create mode 100644 share/qtcreator/examples/10-Drawing/flood_fill.py create mode 100644 share/qtcreator/examples/10-Drawing/image_drawing.py create mode 100644 share/qtcreator/examples/10-Drawing/image_drawing_advanced.py create mode 100644 share/qtcreator/examples/10-Drawing/image_drawing_alpha_blending_test.py create mode 100644 share/qtcreator/examples/10-Drawing/keypoints_drawing.py create mode 100644 share/qtcreator/examples/10-Drawing/line_drawing.py create mode 100644 share/qtcreator/examples/10-Drawing/rectangle_drawing.py create mode 100644 share/qtcreator/examples/10-Drawing/text_drawing.py create mode 100644 share/qtcreator/examples/11-Feature-Detection/edges.py create mode 100644 share/qtcreator/examples/11-Feature-Detection/find_circles.py create mode 100644 share/qtcreator/examples/11-Feature-Detection/find_lines.py create mode 100644 share/qtcreator/examples/11-Feature-Detection/find_rects.py create mode 100644 share/qtcreator/examples/11-Feature-Detection/hog.py create mode 100644 share/qtcreator/examples/11-Feature-Detection/keypoints.py create mode 100644 share/qtcreator/examples/11-Feature-Detection/lbp.py create mode 100644 share/qtcreator/examples/11-Feature-Detection/linear_regression_fast.py create mode 100644 share/qtcreator/examples/11-Feature-Detection/linear_regression_robust.py create mode 100644 share/qtcreator/examples/11-Feature-Detection/template_matching.py create mode 100644 share/qtcreator/examples/12-Image-Filters/adaptive_histogram_equalization.py create mode 100644 share/qtcreator/examples/12-Image-Filters/blur_filter.py create mode 100644 share/qtcreator/examples/12-Image-Filters/cartoon_filter.py create mode 100644 share/qtcreator/examples/12-Image-Filters/color_bilateral_filter.py create mode 100644 share/qtcreator/examples/12-Image-Filters/color_binary_filter.py create mode 100644 share/qtcreator/examples/12-Image-Filters/color_light_removal.py create mode 100644 share/qtcreator/examples/12-Image-Filters/edge_filter.py create mode 100644 share/qtcreator/examples/12-Image-Filters/erode_and_dilate.py create mode 100644 share/qtcreator/examples/12-Image-Filters/gamma_correction.py create mode 100644 share/qtcreator/examples/12-Image-Filters/grayscale_bilateral_filter.py create mode 100644 share/qtcreator/examples/12-Image-Filters/grayscale_binary_filter.py create mode 100644 share/qtcreator/examples/12-Image-Filters/grayscale_light_removal.py create mode 100644 share/qtcreator/examples/12-Image-Filters/histogram_equalization.py create mode 100644 share/qtcreator/examples/12-Image-Filters/kernel_filters.py create mode 100644 share/qtcreator/examples/12-Image-Filters/lens_correction.py create mode 100644 share/qtcreator/examples/12-Image-Filters/linear_polar.py create mode 100644 share/qtcreator/examples/12-Image-Filters/log_polar.py create mode 100644 share/qtcreator/examples/12-Image-Filters/mean_adaptive_threshold_filter.py create mode 100644 share/qtcreator/examples/12-Image-Filters/mean_filter.py create mode 100644 share/qtcreator/examples/12-Image-Filters/median_adaptive_threshold_filter.py create mode 100644 share/qtcreator/examples/12-Image-Filters/median_filter.py create mode 100644 share/qtcreator/examples/12-Image-Filters/midpoint_adaptive_threshold_filter.py create mode 100644 share/qtcreator/examples/12-Image-Filters/midpoint_filter.py create mode 100644 share/qtcreator/examples/12-Image-Filters/mode_adaptive_threshold_filter.py create mode 100644 share/qtcreator/examples/12-Image-Filters/mode_filter.py create mode 100644 share/qtcreator/examples/12-Image-Filters/negative.py create mode 100644 share/qtcreator/examples/12-Image-Filters/perspective_and_rotation_correction.py create mode 100644 share/qtcreator/examples/12-Image-Filters/perspective_correction.py create mode 100644 share/qtcreator/examples/12-Image-Filters/rotation_correction.py create mode 100644 share/qtcreator/examples/12-Image-Filters/sharpen_filter.py create mode 100644 share/qtcreator/examples/12-Image-Filters/unsharp_filter.py create mode 100644 share/qtcreator/examples/12-Image-Filters/vflip_hmirror_transpose.py create mode 100644 share/qtcreator/examples/13-Snapshot/emboss_snapshot.py create mode 100644 share/qtcreator/examples/13-Snapshot/snapshot.py create mode 100644 share/qtcreator/examples/14-Socket/http_client.py create mode 100644 share/qtcreator/examples/14-Socket/http_server.py create mode 100755 share/qtcreator/examples/14-Socket/iperf3.py create mode 100644 share/qtcreator/examples/14-Socket/network_lan.py create mode 100644 share/qtcreator/examples/14-Socket/tcp_client.py create mode 100644 share/qtcreator/examples/14-Socket/tcp_server.py create mode 100644 share/qtcreator/examples/14-Socket/udp_clinet.py create mode 100644 share/qtcreator/examples/14-Socket/udp_server.py create mode 100644 share/qtcreator/examples/15-Utils/db/readme.txt create mode 100644 share/qtcreator/examples/15-Utils/db_img/id_1.jpg create mode 100644 share/qtcreator/examples/15-Utils/db_img/id_2.png create mode 100755 share/qtcreator/examples/15-Utils/dict.txt create mode 100644 share/qtcreator/examples/15-Utils/fist.bin create mode 100644 share/qtcreator/examples/15-Utils/five.bin create mode 100644 share/qtcreator/examples/15-Utils/prior_data_320.bin create mode 100644 share/qtcreator/examples/15-Utils/shear.bin create mode 100644 share/qtcreator/examples/15-Utils/wozai.wav diff --git a/share/qtcreator/examples/01-Media/acodec.py b/share/qtcreator/examples/01-Media/acodec.py old mode 100755 new mode 100644 index 81d60edb02b..ff4906c9e8b --- a/share/qtcreator/examples/01-Media/acodec.py +++ b/share/qtcreator/examples/01-Media/acodec.py @@ -1,22 +1,37 @@ -from media.pyaudio import * -from media.media import * -import media.g711 as g711 -from mpp.payload_struct import * +# g711 encode/decode example +# +# Note: You will need an SD card to run this example. +# +# You can collect raw data and encode it into g711 or decode it into raw data output. + + +from media.pyaudio import * #导入pyaudio模块,用于采集和播放音频 +from media.media import * #导入media模块,用于初始化vb buffer +import media.g711 as g711 #导入g711模块,用于g711编解码 +from mpp.payload_struct import * #导入payload模块,用于获取音视频编解码类型 +import os + +def exit_check(): + try: + os.exitpoint() + except KeyboardInterrupt as e: + print("user stop: ", e) + return True + return False def encode_audio(filename, duration): - CHUNK = int(44100/25) - FORMAT = paInt16 - CHANNELS = 2 - RATE = 44100 + CHUNK = int(44100/25) #设置音频chunk值 + FORMAT = paInt16 #设置采样精度 + CHANNELS = 2 #设置声道数 + RATE = 44100 #设置采样率 p = PyAudio() - p.initialize(CHUNK) - enc = g711.Encoder(K_PT_G711A,CHUNK) - ret = media.buffer_init() - if ret: - print("record_audio, buffer_init failed") + p.initialize(CHUNK) #初始化PyAudio对象 + enc = g711.Encoder(K_PT_G711A,CHUNK) #创建g711编码器对象 + media.buffer_init() #vb buffer初始化 - enc.create() + enc.create() #创建编码器 + #创建音频输入流 stream = p.open(format=FORMAT, channels=CHANNELS, rate=RATE, @@ -24,109 +39,117 @@ def encode_audio(filename, duration): frames_per_buffer=CHUNK) frames = [] - + #采集音频数据编码并存入列表 for i in range(0, int(RATE / CHUNK * duration)): - frame_data = stream.read() - data = enc.encode(frame_data) - frames.append(data) - - stream.stop_stream() - stream.close() - p.terminate() - enc.destroy() - + frame_data = stream.read() #从音频输入流中读取音频数据 + data = enc.encode(frame_data) #编码音频数据为g711 + frames.append(data) #将g711编码数据保存到列表中 + if exit_check(): + break + + stream.stop_stream() #停止音频输入流 + stream.close() #关闭音频输入流 + p.terminate() #释放音频对象 + enc.destroy() #销毁g711音频编码器 + + #将g711编码数据存入文件中 with open(filename,mode='w') as wf: wf.write(b''.join(frames)) - media.buffer_deinit() + media.buffer_deinit() #释放vb buffer def decode_audio(filename): - #读取音频文件 - wf = open(filename,mode='rb') - FORMAT = paInt16 - CHANNELS = 2 - RATE = 44100 - CHUNK = int(RATE/25) - - #播放音频操作 + wf = open(filename,mode='rb') #打开g711文件 + FORMAT = paInt16 #设置音频chunk值 + CHANNELS = 2 #设置声道数 + RATE = 44100 #设置采样率 + CHUNK = int(RATE/25) #设置音频chunk值 + p = PyAudio() - p.initialize(CHUNK) - dec = g711.Decoder(K_PT_G711A,CHUNK) - ret = media.buffer_init() - if ret: - print("play_audio, buffer_init failed") + p.initialize(CHUNK) #初始化PyAudio对象 + dec = g711.Decoder(K_PT_G711A,CHUNK) #创建g711解码器对象 + media.buffer_init() #vb buffer初始化 - dec.create() + dec.create() #创建解码器 + #创建音频输出流 stream = p.open(format=FORMAT, channels=CHANNELS, rate=RATE, output=True, frames_per_buffer=CHUNK) - stream_len = CHUNK*CHANNELS*2//2 - stream_data = wf.read(stream_len) + stream_len = CHUNK*CHANNELS*2//2 #设置每次读取的g711数据流长度 + stream_data = wf.read(stream_len) #从g711文件中读取数据 + #解码g711文件并播放 while stream_data: - frame_data = dec.decode(stream_data) - stream.write(frame_data) - stream_data = wf.read(stream_len) + frame_data = dec.decode(stream_data) #解码g711文件 + stream.write(frame_data) #播放raw数据 + stream_data = wf.read(stream_len) #从g711文件中读取数据 + if exit_check(): + break - stream.stop_stream() - stream.close() - p.terminate() - dec.destroy() - wf.close() + stream.stop_stream() #停止音频输入流 + stream.close() #关闭音频输入流 + p.terminate() #释放音频对象 + dec.destroy() #销毁解码器 + wf.close() #关闭g711文件 - media.buffer_deinit() + media.buffer_deinit() #释放vb buffer def loop_codec(duration): - CHUNK = int(44100/25) - FORMAT = paInt16 - CHANNELS = 2 - RATE = 44100 + CHUNK = int(44100/25) #设置音频chunk值 + FORMAT = paInt16 #设置采样精度 + CHANNELS = 2 #设置声道数 + RATE = 44100 #设置采样率 p = PyAudio() - p.initialize(CHUNK) - dec = g711.Decoder(K_PT_G711A,CHUNK) - enc = g711.Encoder(K_PT_G711A,CHUNK) - ret = media.buffer_init() - if ret: - print("loop_audio, buffer_init failed") + p.initialize(CHUNK) #初始化PyAudio对象 + dec = g711.Decoder(K_PT_G711A,CHUNK) #创建g711解码器对象 + enc = g711.Encoder(K_PT_G711A,CHUNK) #创建g711编码器对象 + media.buffer_init() #vb buffer初始化 - dec.create() - enc.create() + dec.create() #创建g711解码器 + enc.create() #创建g711编码器 + #创建音频输入流 input_stream = p.open(format=FORMAT, channels=CHANNELS, rate=RATE, input=True, frames_per_buffer=CHUNK) + #创建音频输出流 output_stream = p.open(format=FORMAT, channels=CHANNELS, rate=RATE, output=True, frames_per_buffer=CHUNK) + #从音频输入流中获取数据->编码->解码->写入到音频输出流中 for i in range(0, int(RATE / CHUNK * duration)): - frame_data = input_stream.read() - stream_data = enc.encode(frame_data) - frame_data = dec.decode(stream_data) - output_stream.write(frame_data) - - - input_stream.stop_stream() - output_stream.stop_stream() - input_stream.close() - output_stream.close() - p.terminate() - dec.destroy() - enc.destroy() - - media.buffer_deinit() - -#encode_audio('/sdcard/app/test.g711a', 15) -#decode_audio('/sdcard/app/test.g711a') -loop_codec(15) -print("audio codec sample done") + frame_data = input_stream.read() #从音频输入流中获取raw音频数据 + stream_data = enc.encode(frame_data) #编码音频数据为g711 + frame_data = dec.decode(stream_data) #解码g711数据为raw数据 + output_stream.write(frame_data) #播放raw数据 + if exit_check(): + break + + input_stream.stop_stream() #停止音频输入流 + output_stream.stop_stream() #停止音频输出流 + input_stream.close() #关闭音频输入流 + output_stream.close() #关闭音频输出流 + p.terminate() #释放音频对象 + dec.destroy() #销毁g711解码器 + enc.destroy() #销毁g711编码器 + + media.buffer_deinit() #释放vb buffer + +if __name__ == "__main__": + os.exitpoint(os.EXITPOINT_ENABLE) + print("audio codec sample start") + #encode_audio('/sdcard/app/test.g711a', 15) #采集并编码g711文件 + #decode_audio('/sdcard/app/test.g711a') #解码g711文件并输出 + loop_codec(15) #采集音频数据->编码g711->解码g711->播放音频 + print("audio codec sample done") diff --git a/share/qtcreator/examples/01-Media/audio.py b/share/qtcreator/examples/01-Media/audio.py old mode 100755 new mode 100644 index 8da52baa5a8..015d9975808 --- a/share/qtcreator/examples/01-Media/audio.py +++ b/share/qtcreator/examples/01-Media/audio.py @@ -1,19 +1,33 @@ -from media.pyaudio import * -import media.wave as wave -from media.media import * +# audio input and output example +# +# Note: You will need an SD card to run this example. +# +# You can play wav files or capture audio to save as wav + +from media.pyaudio import * #导入pyaudio模块,用于采集和播放音频 +import media.wave as wave #导入wav模块,用于保存和加载wav音频文件 +from media.media import * #导入media模块,用于初始化vb buffer +import os + +def exit_check(): + try: + os.exitpoint() + except KeyboardInterrupt as e: + print("user stop: ", e) + return True + return False def record_audio(filename, duration): - CHUNK = int(44100/25) - FORMAT = paInt16 - CHANNELS = 2 - RATE = 44100 + CHUNK = int(44100/25) #设置音频chunk值 + FORMAT = paInt16 #设置采样精度 + CHANNELS = 2 #设置声道数 + RATE = 44100 #设置采样率 p = PyAudio() - p.initialize(CHUNK) - ret = media.buffer_init() - if ret: - print("record_audio, buffer_init failed") + p.initialize(CHUNK) #初始化PyAudio对象 + media.buffer_init() #vb buffer初始化 + #创建音频输入流 stream = p.open(format=FORMAT, channels=CHANNELS, rate=RATE, @@ -21,90 +35,99 @@ def record_audio(filename, duration): frames_per_buffer=CHUNK) frames = [] - + #采集音频数据并存入列表 for i in range(0, int(RATE / CHUNK * duration)): data = stream.read() frames.append(data) + if exit_check(): + break - stream.stop_stream() - stream.close() - p.terminate() + stream.stop_stream() #停止采集音频数据 + stream.close()#关闭音频输入流 + p.terminate()#释放音频对象 - wf = wave.open(filename, 'wb') - wf.set_channels(CHANNELS) - wf.set_sampwidth(p.get_sample_size(FORMAT)) - wf.set_framerate(RATE) - wf.write_frames(b''.join(frames)) - wf.close() + #将列表中的数据保存到wav文件中 + wf = wave.open(filename, 'wb') #创建wav 文件 + wf.set_channels(CHANNELS) #设置wav 声道数 + wf.set_sampwidth(p.get_sample_size(FORMAT)) #设置wav 采样精度 + wf.set_framerate(RATE) #设置wav 采样率 + wf.write_frames(b''.join(frames)) #存储wav音频数据 + wf.close() #关闭wav文件 - media.buffer_deinit() + media.buffer_deinit() #释放vb buffer def play_audio(filename): - #读取音频文件 - wf = wave.open(filename, 'rb') - CHUNK = int(wf.get_framerate()/25) - #播放音频操作 + wf = wave.open(filename, 'rb')#打开wav文件 + CHUNK = int(wf.get_framerate()/25)#设置音频chunk值 + p = PyAudio() - p.initialize(CHUNK) - ret = media.buffer_init() - if ret: - print("play_audio, buffer_init failed") + p.initialize(CHUNK) #初始化PyAudio对象 + media.buffer_init()#vb buffer初始化 + #创建音频输出流,设置的音频参数均为wave中获取到的参数 stream = p.open(format=p.get_format_from_width(wf.get_sampwidth()), channels=wf.get_channels(), rate=wf.get_framerate(), output=True,frames_per_buffer=CHUNK) - data = wf.read_frames(CHUNK) + + data = wf.read_frames(CHUNK)#从wav文件中读取数一帧数据 while data: - stream.write(data) - data = wf.read_frames(CHUNK) + stream.write(data) #将帧数据写入到音频输出流中 + data = wf.read_frames(CHUNK) #从wav文件中读取数一帧数据 + if exit_check(): + break - stream.stop_stream() - stream.close() - p.terminate() - wf.close() + stream.stop_stream() #停止音频输出流 + stream.close()#关闭音频输出流 + p.terminate()#释放音频对象 + wf.close()#关闭wav文件 - media.buffer_deinit() + media.buffer_deinit()#释放vb buffer def loop_audio(duration): - CHUNK = int(44100/25) - FORMAT = paInt16 - CHANNELS = 2 - RATE = 44100 + CHUNK = int(44100/25)#设置音频chunck + FORMAT = paInt16 #设置音频采样精度 + CHANNELS = 2 #设置音频声道数 + RATE = 44100 #设置音频采样率 p = PyAudio() - p.initialize(CHUNK) - ret = media.buffer_init() - if ret: - print("loop_audio, buffer_init failed") + p.initialize(CHUNK)#初始化PyAudio对象 + media.buffer_init() #初始化vb buffer + #创建音频输入流 input_stream = p.open(format=FORMAT, channels=CHANNELS, rate=RATE, input=True, frames_per_buffer=CHUNK) + #创建音频输出流 output_stream = p.open(format=FORMAT, channels=CHANNELS, rate=RATE, output=True,frames_per_buffer=CHUNK) + #从音频输入流中获取数据写入到音频输出流中 for i in range(0, int(RATE / CHUNK * duration)): output_stream.write(input_stream.read()) - - - input_stream.stop_stream() - output_stream.stop_stream() - input_stream.close() - output_stream.close() - p.terminate() - - media.buffer_deinit() - -#play_audio('/sdcard/app/input.wav') -#record_audio('/sdcard/app/output.wav', 15) -loop_audio(15) -print("audio sample done") + if exit_check(): + break + + input_stream.stop_stream()#停止音频输入流 + output_stream.stop_stream()#停止音频输出流 + input_stream.close() #关闭音频输入流 + output_stream.close() #关闭音频输出流 + p.terminate() #释放音频对象 + + media.buffer_deinit() #释放vb buffer + +if __name__ == "__main__": + os.exitpoint(os.EXITPOINT_ENABLE) + print("audio sample start") + #play_audio('/sdcard/app/input.wav') #播放wav文件 + #record_audio('/sdcard/app/output.wav', 15) #录制wav文件 + loop_audio(15) #采集音频并输出 + print("audio sample done") diff --git a/share/qtcreator/examples/01-Media/camera.py b/share/qtcreator/examples/01-Media/camera.py index c8d4f370506..d27ef0d0f2a 100755 --- a/share/qtcreator/examples/01-Media/camera.py +++ b/share/qtcreator/examples/01-Media/camera.py @@ -1,116 +1,94 @@ +# Camera Example +# +# Note: You will need an SD card to run this example. +# +# You can start camera preview and capture yuv image. + from media.camera import * from media.display import * from media.media import * -from time import * -import time -import image - - -def canmv_camera_test(): - print("canmv_camera_test") +import time, os +def camera_test(): + print("camera_test") # use hdmi for display display.init(LT9611_1920X1080_30FPS) - - # use EVB LCD for display - #display.init(HX8377_1080X1920_30FPS) - camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) - #camera.sensor_init(CAM_DEV_ID_0, CAM_IMX335_2LANE_1920X1080_30FPS_12BIT_LINEAR) - out_width = 1920 out_height = 1080 + # set camera out width align up with 16Bytes out_width = ALIGN_UP(out_width, 16) - - # set chn0 output yuv420sp + # set chn0 output size camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, out_width, out_height) + # set chn0 out format camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) - + # create meida source device meida_source = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device meida_sink = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link media.create_link(meida_source, meida_sink) - + # set display plane with video channel display.set_plane(0, 0, out_width, out_height, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) - out_width = 640 out_height = 480 out_width = ALIGN_UP(out_width, 16) - - # set chn1 output rgb888 + # set chn1 output size camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, out_width, out_height) + # set chn1 output format camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_RGB_888) - - # set chn2 output rgb888planar + # set chn1 output size camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_2, out_width, out_height) + # set chn2 output format camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_2, PIXEL_FORMAT_RGB_888_PLANAR) - - ret = media.buffer_init() - if ret: - print("canmv_camera_test, buffer init failed") - return ret - + # init meida buffer + media.buffer_init() + # start stream for camera device0 camera.start_stream(CAM_DEV_ID_0) - time.sleep(15) - - capture_count = 0 - while capture_count < 100: - time.sleep(1) - for dev_num in range(CAM_DEV_ID_MAX): - if not camera.cam_dev[dev_num].dev_attr.dev_enable: - continue - - for chn_num in range(CAM_CHN_ID_MAX): - if not camera.cam_dev[dev_num].chn_attr[chn_num].chn_enable: + try: + while True: + os.exitpoint() + time.sleep(5) + for dev_num in range(CAM_DEV_ID_MAX): + if not camera.cam_dev[dev_num].dev_attr.dev_enable: continue - print(f"canmv_camera_test, dev({dev_num}) chn({chn_num}) capture frame.") - - img = camera.capture_image(dev_num, chn_num) - if img == -1: - print("camera.capture_image failed") - continue - - if img.format() == image.YUV420: - suffix = "yuv420sp" - elif img.format() == image.RGB888: - suffix = "rgb888" - elif img.format() == image.RGBP888: - suffix = "rgb888p" - else: - suffix = "unkown" - - filename = f"/sdcard/dev_{dev_num:02d}_chn_{chn_num:02d}_{img.width()}x{img.height()}_{capture_count:04d}.{suffix}" - print("save capture image to file:", filename) - - with open(filename, "wb") as f: - if f: - img_data = uctypes.bytearray_at(img.virtaddr(), img.size()) - #f.write(img_data) + for chn_num in range(CAM_CHN_ID_MAX): + if not camera.cam_dev[dev_num].chn_attr[chn_num].chn_enable: + continue + + print(f"camera_test, dev({dev_num}) chn({chn_num}) capture frame.") + # capture image from dev and chn + img = camera.capture_image(dev_num, chn_num) + if img.format() == image.YUV420: + suffix = "yuv420sp" + elif img.format() == image.RGB888: + suffix = "rgb888" + elif img.format() == image.RGBP888: + suffix = "rgb888p" else: - print(f"capture_image, open dump file failed({filename})") - - time.sleep(1) - - camera.release_image(dev_num, chn_num, img) - - capture_count += 1 - + suffix = "unkown" + + filename = f"/sdcard/dev_{dev_num:02d}_chn_{chn_num:02d}_{img.width()}x{img.height()}.{suffix}" + print("save capture image to file:", filename) + img.save(filename) + # release image for dev and chn + camera.release_image(dev_num, chn_num, img) + except KeyboardInterrupt as e: + print("user stop: ", e) + except BaseException as e: + sys.print_exception(e) + # stop stream for camera device0 camera.stop_stream(CAM_DEV_ID_0) - + # deinit display display.deinit() - + # destroy media link media.destroy_link(meida_source, meida_sink) - - time.sleep(1) - - ret = media.buffer_deinit() - if ret: - print("camera test, media_buffer_deinit failed") - return ret - - print("camera test exit") - return 0 - - -canmv_camera_test() - + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # deinit media buffer + media.buffer_deinit() + +if __name__ == "__main__": + os.exitpoint(os.EXITPOINT_ENABLE) + camera_test() diff --git a/share/qtcreator/examples/01-Media/camera_480p.py b/share/qtcreator/examples/01-Media/camera_480p.py new file mode 100644 index 00000000000..fb767130b1a --- /dev/null +++ b/share/qtcreator/examples/01-Media/camera_480p.py @@ -0,0 +1,69 @@ +from media.camera import * +from media.display import * +from media.media import * +from time import * +import time +import image +from mpp import * +import gc +from random import randint + +def canmv_camera_test(): + print("canmv_camera_test") + + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + + # use EVB LCD for display + # display.init(HX8377_1080X1920_30FPS) + + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + + out_width = 640 + out_height = 480 + out_width = ALIGN_UP(out_width, 16) + + # set chn0 output yuv420sp + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, out_width, out_height) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + + meida_source = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + meida_sink = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + media.create_link(meida_source, meida_sink) + + display.set_plane(0, 0, out_width, out_height, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + + ret = media.buffer_init() + if ret: + print("canmv_camera_test, buffer init failed") + return ret + + camera.start_stream(CAM_DEV_ID_0) + img = None + try: + capture_count = 0 + while True: + img = camera.capture_image(0, 0) + img.compress_for_ide() + camera.release_image(0, 0, img) + gc.collect() + capture_count += 1 + print(capture_count) + except Exception as e: + print(f"An error occurred during buffer used: {e}") + finally: + print('end') + if img: + camera.release_image(0, 0, img) + else: + print('img not dumped') + camera.stop_stream(CAM_DEV_ID_0) + + display.deinit() + + media.destroy_link(meida_source, meida_sink) + time.sleep(1) + print("camera test exit") + return 0 + +canmv_camera_test() diff --git a/share/qtcreator/examples/01-Media/display.py b/share/qtcreator/examples/01-Media/display.py index b24698cf7f6..2e0145e5199 100755 --- a/share/qtcreator/examples/01-Media/display.py +++ b/share/qtcreator/examples/01-Media/display.py @@ -1,53 +1,67 @@ from media.camera import * from media.display import * from media.media import * -from time import * -import time +import time, os, urandom, sys +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 -def camera_display_test(): - CAM_OUTPUT_BUF_NUM = 6 - CAM_INPUT_BUF_NUM = 4 - - out_width = 1080 - out_height = 720 - out_width = ALIGN_UP(out_width, 16) - +def display_test(): + print("display test") + # use hdmi for display display.init(LT9611_1920X1080_30FPS) - camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) - - # set chn0 - camera.set_outbufs(CAM_DEV_ID_0, CAM_CHN_ID_0, CAM_OUTPUT_BUF_NUM) - camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, out_width, out_height) - camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) - - meida_source = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) - meida_sink = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) - media.create_link(meida_source, meida_sink) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) - display.set_plane(400, 200, out_width, out_height, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # create image for drawing + img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888) + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + try: + while True: + img.clear() + for i in range(10): + x = (urandom.getrandbits(11) % img.width()) + y = (urandom.getrandbits(11) % img.height()) + r = (urandom.getrandbits(8)) + g = (urandom.getrandbits(8)) + b = (urandom.getrandbits(8)) + # If the first argument is a scaler then this method expects + # to see x, y, and text. Otherwise, it expects a (x,y,text) tuple. + # Character and string rotation can be done at 0, 90, 180, 270, and etc. degrees. + img.draw_string(x, y, "Hello World!", color = (r, g, b), scale = 2, mono_space = False, + char_rotation = 0, char_hmirror = False, char_vflip = False, + string_rotation = 0, string_hmirror = False, string_vflip = False) + img.copy_to(osd_img) + time.sleep(1) + os.exitpoint() + except KeyboardInterrupt as e: + print("user stop: ", e) + except BaseException as e: + sys.print_exception(e) - ret = media.buffer_init() - if ret: - print("camera_display_test, buffer init failed") - return ret - - camera.start_stream(CAM_DEV_ID_0) - count = 0 - while count < 600: - time.sleep(1) - count += 1 - - camera.stop_stream(CAM_DEV_ID_0) - media.destroy_link(meida_source, meida_sink) - time.sleep(1) + # deinit display display.deinit() - ret = media.buffer_deinit() - if ret: - print("camera_display_test, media_buffer_deinit failed") - return ret - - print("camera_display_test exit") - return 0 + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # deinit media buffer + media.buffer_deinit() -camera_display_test() +if __name__ == "__main__": + os.exitpoint(os.EXITPOINT_ENABLE) + display_test() diff --git a/share/qtcreator/examples/01-Media/media.py b/share/qtcreator/examples/01-Media/media.py index c491468aec1..805e2a06aa4 100755 --- a/share/qtcreator/examples/01-Media/media.py +++ b/share/qtcreator/examples/01-Media/media.py @@ -1,28 +1,15 @@ -from media.media import * +# Meida Example +# +# Note: You will need an SD card to run this example. +# +# You can get how to use the meida api form this example. +from media.media import * +import os def media_buf_test(): print("media_buf_test start") config = k_vb_config() - config.max_pool_cnt = 10 - - config.comm_pool[0].blk_size = 1024*1024 - config.comm_pool[0].blk_cnt = 10 - config.comm_pool[0].mode = VB_REMAP_MODE_NONE - - config.comm_pool[1].blk_size = 2*1024*1024 - config.comm_pool[1].blk_cnt = 10 - config.comm_pool[1].mode = VB_REMAP_MODE_NOCACHE - - config.comm_pool[2].blk_size = 3*1024*1024 - config.comm_pool[2].blk_cnt = 10 - config.comm_pool[3].mode = VB_REMAP_MODE_CACHED - - print("media_buf_test buffer_config 111") - ret = media.buffer_config(config) - if ret: - print("media_buf_test, buffer_config failed") - return ret config.max_pool_cnt = 10 @@ -38,11 +25,8 @@ def media_buf_test(): config.comm_pool[2].blk_cnt = 10 config.comm_pool[3].mode = VB_REMAP_MODE_CACHED - print("media_buf_test buffer_config 222") - ret = media.buffer_config(config) - if ret: - print("media_buf_test, buffer_config failed") - return ret + # config meida buffer + media.buffer_config(config) config.max_pool_cnt = 20 @@ -58,11 +42,8 @@ def media_buf_test(): config.comm_pool[2].blk_cnt = 3 config.comm_pool[3].mode = VB_REMAP_MODE_CACHED - print("media_buf_test buffer_config 333") - ret = media.buffer_config(config) - if ret: - print("media_buf_test, buffer_config failed") - return ret + # config meida buffer + media.buffer_config(config) config.max_pool_cnt = 30 @@ -78,40 +59,30 @@ def media_buf_test(): config.comm_pool[2].blk_cnt = 5 config.comm_pool[3].mode = VB_REMAP_MODE_CACHED - print("media_buf_test buffer_config 444") - ret = media.buffer_config(config) - if ret: - print("media_buf_test, buffer_config failed") - return ret + # config meida buffer + media.buffer_config(config) print("media_buf_test buffer_init") - ret = media.buffer_init() - if ret: - print("media_buf_test, buffer_init failed") - + # init meida buffer + media.buffer_init() print("media_buf_test request_buffer") + # request meida buffer buffer = media.request_buffer(4*1024*1024) - if buffer == -1: - print("media_buf_test, request_buffer failed") - else: - print(f"buffer handle({buffer.handle})") - print(f"buffer pool_id({buffer.pool_id})") - print(f"buffer phys_addr({buffer.phys_addr})") - print(f"buffer virt_addr({buffer.virt_addr})") - print(f"buffer size({buffer.size})") - ret = media.release_buffer(buffer) - if ret: - print("media_buf_test, release_buffer failed") + print(f"buffer handle({buffer.handle})") + print(f"buffer pool_id({buffer.pool_id})") + print(f"buffer phys_addr({buffer.phys_addr})") + print(f"buffer virt_addr({buffer.virt_addr})") + print(f"buffer size({buffer.size})") + # release meida buffer + media.release_buffer(buffer) print("media_buf_test buffer_deinit") - ret = media.buffer_deinit() - if ret: - print("media_buf_test, buffer_deinit failed") - return ret + # deinit meida buffer + media.buffer_deinit() print("media_buf_test end") - return 0 - -media_buf_test() +if __name__ == "__main__": + os.exitpoint(os.EXITPOINT_ENABLE) + media_buf_test() diff --git a/share/qtcreator/examples/01-Media/mp4muxer.py b/share/qtcreator/examples/01-Media/mp4muxer.py old mode 100755 new mode 100644 index 37fe60580e3..978b65e9077 --- a/share/qtcreator/examples/01-Media/mp4muxer.py +++ b/share/qtcreator/examples/01-Media/mp4muxer.py @@ -1,48 +1,45 @@ +# Save MP4 file example +# +# Note: You will need an SD card to run this example. +# +# You can capture audio and video and save them as MP4.The current version only supports MP4 format, video supports 264/265, and audio supports g711a/g711u. + from media.mp4format import * +import os -def canmv_mp4_muxer_test(): +def mp4_muxer_test(): + print("mp4_muxer_test start") width = 1280 height = 720 + # 实例化mp4 container mp4_muxer = Mp4Container() - mp4_cfg = Mp4CfgStr(mp4_muxer.MP4_CONFIG_TYPE_MUXER) if mp4_cfg.type == mp4_muxer.MP4_CONFIG_TYPE_MUXER: file_name = "/sdcard/app/tests/test.mp4" mp4_cfg.SetMuxerCfg(file_name, mp4_muxer.MP4_CODEC_ID_H265, width, height, mp4_muxer.MP4_CODEC_ID_G711U) - - ret = mp4_muxer.Create(mp4_cfg) - if ret: - print("canmv_mp4_muxer_test, mp4 muxer Create failed.") - return -1 - - ret = mp4_muxer.Start() - if ret: - print("canmv_mp4_muxer_test, mp4 muxer Start failed.") - return -1 + # 创建mp4 muxer + mp4_muxer.Create(mp4_cfg) + # 启动mp4 muxer + mp4_muxer.Start() frame_count = 0 - - while True: - ret = mp4_muxer.Process() - if ret: - print("canmv_mp4_muxer_test, mp4 muxer Process failed.") - return -1 - - frame_count += 1 - print("frame_coutn = ", frame_count) - if frame_count >= 100: - break - - ret = mp4_muxer.Stop() - if ret: - print("canmv_mp4_muxer_test, mp4 muxer Stop failed.") - return -1 - - ret = mp4_muxer.Destroy() - if ret: - print("canmv_mp4_muxer_test, mp4 muxer Destroy failed.") - return -1 - - return 0 - -canmv_mp4_muxer_test() \ No newline at end of file + try: + while True: + os.exitpoint() + # 处理音视频数据,按MP4格式写入文件 + mp4_muxer.Process() + frame_count += 1 + print("frame_coutn = ", frame_count) + if frame_count >= 200: + break + except BaseException as e: + print(e) + # 停止mp4 muxer + mp4_muxer.Stop() + # 销毁mp4 muxer + mp4_muxer.Destroy() + print("mp4_muxer_test stop") + +if __name__ == "__main__": + os.exitpoint(os.EXITPOINT_ENABLE) + mp4_muxer_test() diff --git a/share/qtcreator/examples/01-Media/player.py b/share/qtcreator/examples/01-Media/player.py old mode 100755 new mode 100644 index 2a477e39c52..c000ee4d699 --- a/share/qtcreator/examples/01-Media/player.py +++ b/share/qtcreator/examples/01-Media/player.py @@ -1,43 +1,39 @@ -from media.player import * +# play mp4 file example +# +# Note: You will need an SD card to run this example. +# +# You can load local files to play. The current version only supports MP4 format, video supports 264/265, and audio supports g711a/g711u. -start_play = False +from media.player import * #导入播放器模块,用于播放mp4文件 +import os + +start_play = False #播放结束flag def player_event(event,data): global start_play - if(event == K_PLAYER_EVENT_EOF): - start_play = False + if(event == K_PLAYER_EVENT_EOF): #播放结束标识 + start_play = False #设置播放结束标识 def play_mp4_test(filename): global start_play - player=Player() - player.load(filename) - player.set_event_callback(player_event) - player.start() + player=Player() #创建播放器对象 + player.load(filename) #加载mp4文件 + player.set_event_callback(player_event) #设置播放器事件回调 + player.start() #开始播放 start_play = True - while(start_play): - time.sleep(0.1) - - player.stop() + #等待播放结束 + try: + while(start_play): + time.sleep(0.1) + os.exitpoint() + except KeyboardInterrupt as e: + print("user stop: ", e) + except BaseException as e: + sys.print_exception(e) + + player.stop() #停止播放 print("play over") -''' -def test(filename): - player=Player() - print("....load_mp4") - player.load(filename) - time.sleep(1) - print("....destroy_mp4") - player.destroy_mp4(); - - - print("======_init_media_buffer before") - time.sleep(1) - player._init_media_buffer() - print("======_init_media_buffer end") - time.sleep(3) - print("======_deinit_media_buffer before") - player._deinit_media_buffer() - print("======_deinit_media_buffer end") -''' - -play_mp4_test("/sdcard/app/tests/test.mp4") \ No newline at end of file +if __name__ == "__main__": + os.exitpoint(os.EXITPOINT_ENABLE) + play_mp4_test("/sdcard/app/tests/test.mp4")#播放mp4文件 diff --git a/share/qtcreator/examples/01-Media/venc.py b/share/qtcreator/examples/01-Media/venc.py old mode 100755 new mode 100644 index 861ddf2f8da..1711083a3bd --- a/share/qtcreator/examples/01-Media/venc.py +++ b/share/qtcreator/examples/01-Media/venc.py @@ -1,58 +1,46 @@ +# Video encode example +# +# Note: You will need an SD card to run this example. +# +# You can capture videos and encode them into 264 files + from media.vencoder import * from media.camera import * from media.media import * -from time import * -import time +import time, os -def canmv_venc_test(): +def venc_test(): + print("venc_test start") width = 1280 height = 720 venc_chn = VENC_CHN_ID_0 - width = ALIGN_UP(width, 16) + # 初始化sensor camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) - - # set vicap chn0 + # 设置camera 输出buffer camera.set_outbufs(CAM_DEV_ID_0, CAM_CHN_ID_0, 6) + # 设置camera 输出buffer size camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, width, height) + # 设置camera 输出格式 camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) - + # 实例化video encoder encoder = Encoder() - ret = encoder.SetOutBufs(venc_chn, 15, width, height) - if ret: - print("canmv_venc_test, encoder SetOutBufs failed.") - return -1 - - ret = media.buffer_init() - if ret: - print("canmv_venc_test, buffer_init failed.") - return ret - + # 设置video encoder 输出buffer + encoder.SetOutBufs(venc_chn, 15, width, height) + # 初始化设置的buffer + media.buffer_init() chnAttr = ChnAttrStr(encoder.PAYLOAD_TYPE_H265, encoder.H265_PROFILE_MAIN, width, height) streamData = StreamData() - - ret = encoder.Create(venc_chn, chnAttr) - if ret < 0: - print("canmv_venc_test, vencoder create filed.") - return ret - - # Bind with camera + # 创建编码器 + encoder.Create(venc_chn, chnAttr) + # 绑定camera和venc media_source = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) media_sink = media_device(VIDEO_ENCODE_MOD_ID, VENC_DEV_ID, venc_chn) - ret = media.create_link(media_source, media_sink) - if ret: - print("cam_venc_test, create link with camera failed.") - return ret - - ret = encoder.Start(venc_chn) - if ret: - print("cam_venc_test, encoder start failed") - return ret - - ret = camera.start_stream(CAM_DEV_ID_0) - if ret: - print("cam_venc_test, camera start failed") - return ret + media.create_link(media_source, media_sink) + # 开始编码 + encoder.Start(venc_chn) + # 启动camera + camera.start_stream(CAM_DEV_ID_0) frame_count = 0 if chnAttr.payload_type == encoder.PAYLOAD_TYPE_H265: @@ -62,53 +50,43 @@ def canmv_venc_test(): else: suffix = "unkown" print("cam_venc_test, venc payload_type unsupport") - return -1 out_file = f"/sdcard/app/tests/venc_chn_{venc_chn:02d}.{suffix}" print("save stream to file: ", out_file) with open(out_file, "wb") as fo: - while True: - ret = encoder.GetStream(venc_chn, streamData) - if ret < 0: - print("cam_venc_test, venc get stream failed") - return ret - - for pack_idx in range(0, streamData.pack_cnt): - stream_data = uctypes.bytearray_at(streamData.data[pack_idx], streamData.data_size[pack_idx]) - fo.write(stream_data) - print("stream size: ", streamData.data_size[pack_idx], "stream type: ", streamData.stream_type[pack_idx]) - - ret = encoder.ReleaseStream(venc_chn, streamData) - if ret < 0: - print("cam_venc_test, venc release stream failed") - return ret - - frame_count += 1 - if frame_count >= 100: - break - + try: + while True: + os.exitpoint() + encoder.GetStream(venc_chn, streamData) # 获取一帧码流 + + for pack_idx in range(0, streamData.pack_cnt): + stream_data = uctypes.bytearray_at(streamData.data[pack_idx], streamData.data_size[pack_idx]) + fo.write(stream_data) # 码流写文件 + print("stream size: ", streamData.data_size[pack_idx], "stream type: ", streamData.stream_type[pack_idx]) + + encoder.ReleaseStream(venc_chn, streamData) # 释放一帧码流 + + frame_count += 1 + if frame_count >= 100: + break + except KeyboardInterrupt as e: + print("user stop: ", e) + except BaseException as e: + sys.print_exception(e) + + # 停止camera camera.stop_stream(CAM_DEV_ID_0) - - ret = media.destroy_link(media_source, media_sink) - if ret: - print("cam_venc_test, venc destroy link with camera failed.") - return ret - - ret = encoder.Stop(venc_chn) - if ret < 0: - print("cam_venc_test, venc stop failed.") - return ret - - ret = encoder.Destroy(venc_chn) - if ret < 0: - print("cam_venc_test, venc destroy failed.") - return ret - - ret = media.buffer_deinit() - if ret: - print("cam_venc_test, media buffer deinit failed.") - return ret - - -canmv_venc_test() + # 销毁camera和venc的绑定 + media.destroy_link(media_source, media_sink) + # 停止编码 + encoder.Stop(venc_chn) + # 销毁编码器 + encoder.Destroy(venc_chn) + # 清理buffer + media.buffer_deinit() + print("venc_test stop") + +if __name__ == "__main__": + os.exitpoint(os.EXITPOINT_ENABLE) + venc_test() diff --git a/share/qtcreator/examples/02-Machine/adc/adc.py b/share/qtcreator/examples/02-Machine/adc/adc.py old mode 100755 new mode 100644 index 4266a9cb793..fa1e2048460 --- a/share/qtcreator/examples/02-Machine/adc/adc.py +++ b/share/qtcreator/examples/02-Machine/adc/adc.py @@ -1,6 +1,10 @@ +# 基础示例 +# +# 欢迎使用CanMV IDE, 点击IDE左下角的绿色按钮开始执行脚本 + from machine import ADC -adc = ADC(0,enable=True) -value = adc.value() +adc = ADC(0,enable=True) #构造adc对象,通道0默认开启 +value = adc.value() #获取通道0的数值 print("value = %d" % value) -adc.deinit() +adc.deinit() #注销adc对象 diff --git a/share/qtcreator/examples/02-Machine/fft/fft.py b/share/qtcreator/examples/02-Machine/fft/fft.py old mode 100755 new mode 100644 index 3a1342c46f4..c4584d6e31e --- a/share/qtcreator/examples/02-Machine/fft/fft.py +++ b/share/qtcreator/examples/02-Machine/fft/fft.py @@ -1,3 +1,7 @@ +# 基础示例 +# +# 欢迎使用CanMV IDE, 点击IDE左下角的绿色按钮开始执行脚本 + from machine import FFT import array import math @@ -13,18 +17,18 @@ def input_data(): data3 = 0.2 * math.cos(4 * 2 * PI * i / 64) data4 = 1000 * math.cos(5 * 2 * PI * i / 64) rx.append((int(data0 + data1 + data2 + data3 + data4))) -input_data() +input_data() #初始化需要进行FFT的数据,列表类型 print(rx) -data = np.array(rx,dtype=np.uint16) +data = np.array(rx,dtype=np.uint16) #把列表数据转换成数组 print(data) -fft1 = FFT(data, 64, 0x555) -res = fft1.run() +fft1 = FFT(data, 64, 0x555) #创建一个FFT对象,运算点数为64,偏移是0x555 +res = fft1.run() #获取FFT转换后的数据 print(res) -res = fft1.amplitude(res) +res = fft1.amplitude(res) #获取各个频率点的幅值 print(res) -res = fft1.freq(64,38400) +res = fft1.freq(64,38400) #获取所有频率点的频率值 print(res) diff --git a/share/qtcreator/examples/02-Machine/fpioa/fpioa.py b/share/qtcreator/examples/02-Machine/fpioa/fpioa.py old mode 100755 new mode 100644 index e0e585350f5..6c32c8d7f65 --- a/share/qtcreator/examples/02-Machine/fpioa/fpioa.py +++ b/share/qtcreator/examples/02-Machine/fpioa/fpioa.py @@ -15,8 +15,12 @@ a.set_function(60,set_sl=1,set_ie=0,set_oe=0,set_pd=1,set_pu=0,set_ds=6,set_st=0,set_di=1) a.help(60) +try : + print(a.set_function(60,set_msc=0)) + +except Exception as e: + print("set error ", e) -a.set_function(60,set_msc=0) a.help(60) diff --git a/share/qtcreator/examples/02-Machine/gpio/gpio.py b/share/qtcreator/examples/02-Machine/gpio/gpio.py old mode 100755 new mode 100644 index 2a9f9616e74..e6b3e865f00 --- a/share/qtcreator/examples/02-Machine/gpio/gpio.py +++ b/share/qtcreator/examples/02-Machine/gpio/gpio.py @@ -1,13 +1,12 @@ +# 基础示例 +# +# 欢迎使用CanMV IDE, 点击IDE左下角的绿色按钮开始执行脚本 + from machine import GPIO -gpio = GPIO(8, GPIO.OUT, GPIO.PULL_UP, value=0) -value = gpio.value() -print("value = %d" % value) -gpio.value(1) +gpio = GPIO(8, GPIO.OUT, GPIO.PULL_UP, value=0) #构造GPIO对象,gpio编号为8,设置为上拉输出低电平 +value = gpio.value() #获取gpio的值 +print("value = %d" % value) +gpio.value(1) #设置gpio输出为高电平 value = gpio.value() print("value = %d" % value) - -def on_timer(arg): - print("time up: %d" % arg) - -gpio.irq(on_timer,3) diff --git a/share/qtcreator/examples/02-Machine/i2c/i2c.py b/share/qtcreator/examples/02-Machine/i2c/i2c.py index bfaaf35246e..ac1e19afda9 100755 --- a/share/qtcreator/examples/02-Machine/i2c/i2c.py +++ b/share/qtcreator/examples/02-Machine/i2c/i2c.py @@ -1,32 +1,27 @@ from machine import I2C -i2c4=machine.I2C(4) +i2c4=I2C(4) # init i2c4 -i2c4.scan() +a=i2c4.scan() #scan i2c slave +print(a) -i2c4.writeto_mem(0x3b,0xff,bytes([0x80]),mem_size=8) -#value =0x17 -i2c4.readfrom_mem(0x3b,0x00,1,mem_size=8) -#value =0x2 -i2c4.readfrom_mem(0x3b,0x01,1,mem_size=8) +i2c4.writeto_mem(0x3b,0xff,bytes([0x80]),mem_size=8) # write hdmi page address(0x80) +i2c4.readfrom_mem(0x3b,0x00,1,mem_size=8) # read hdmi id0 ,value =0x17 +i2c4.readfrom_mem(0x3b,0x01,1,mem_size=8) # read hdmi id1 ,value =0x2 -i2c4.writeto(0x3b,bytes([0xff,0x80]),True) -i2c4.writeto(0x3b,bytes([0x00]),True) -#value =0x17 -i2c4.readfrom(0x3b,1) -i2c4.writeto(0x3b,bytes([0x01]),True) -#value =0x2 -i2c4.readfrom(0x3b,1) +i2c4.writeto(0x3b,bytes([0xff,0x80]),True) # write hdmi page address(0x80) +i2c4.writeto(0x3b,bytes([0x00]),True) #send the address0 of being readed +i2c4.readfrom(0x3b,1) #read hdmi id0 ,value =0x17 +i2c4.writeto(0x3b,bytes([0x01]),True) #send the address1 of being readed +i2c4.readfrom(0x3b,1) #read hdmi id0 ,value =0x17 -i2c4.writeto_mem(0x3b,0xff,bytes([0x80]),mem_size=8) +i2c4.writeto_mem(0x3b,0xff,bytes([0x80]),mem_size=8) # write hdmi page address(0x80) a=bytearray(1) -i2c4.readfrom_mem_into(0x3b,0x0,a,mem_size=8) -#value =0x17 -print(a) +i2c4.readfrom_mem_into(0x3b,0x0,a,mem_size=8) # read hdmi id0 into a ,value =0x17 +print(a) #printf a,value =0x17 -i2c4.writeto(0x3b,bytes([0xff,0x80]),True) -i2c4.writeto(0x3b,bytes([0x00]),True) +i2c4.writeto(0x3b,bytes([0xff,0x80]),True) # write hdmi page address(0x80) +i2c4.writeto(0x3b,bytes([0x00]),True) #send the address0 of being readed b=bytearray(1) -i2c4.readfrom_into(0x3b,b) -#value =0x17 -print(b) \ No newline at end of file +i2c4.readfrom_into(0x3b,b) #read hdmi id0 into b ,value =0x17 +print(b) #printf a,value =0x17 \ No newline at end of file diff --git a/share/qtcreator/examples/02-Machine/pwm/pwm.py b/share/qtcreator/examples/02-Machine/pwm/pwm.py old mode 100755 new mode 100644 index 816b6f4bcc7..97927cb4217 --- a/share/qtcreator/examples/02-Machine/pwm/pwm.py +++ b/share/qtcreator/examples/02-Machine/pwm/pwm.py @@ -1,4 +1,11 @@ from machine import PWM - -# channel 0 output freq 1kHz duty 50%, enable +# 实例化PWM通道0,频率为1000Hz,占空比为50%,默认使能输出 pwm0 = PWM(0, 1000, 50, enable = True) +# 关闭通道0输出 +pwm0.enable(0) +# 调整通道0频率为2000Hz +pwm0.freq(2000) +# 调整通道0占空比为40% +pwm0.duty(40) +# 打开通道0输出 +pwm0.enable(1) diff --git a/share/qtcreator/examples/02-Machine/spi/spi.py b/share/qtcreator/examples/02-Machine/spi/spi.py new file mode 100755 index 00000000000..929056623fd --- /dev/null +++ b/share/qtcreator/examples/02-Machine/spi/spi.py @@ -0,0 +1,35 @@ +from machine import SPI +from machine import FPIOA +a = FPIOA() + +a.help(14) +a.set_function(14,a.QSPI0_CS0) +a.help(14) + +a.help(15) +a.set_function(15,a.QSPI0_CLK) +a.help(15) + +a.help(16) +a.set_function(16,a.QSPI0_D0) +a.help(16) + +a.help(17) +a.set_function(17,a.QSPI0_D1) +a.help(17) + +spi=SPI(1,baudrate=5000000, polarity=0, phase=0, bits=8) # spi init clock 5MHz, polarity 0, phase 0, data bitwide 8bits + +spi.write(bytes([0x66])) # enable gd25lq128 reset + +spi.write(bytes([0x99])) # gd25lq128 reset + +a=bytes([0x9f]) # send buff +b=bytearray(3) # receive buf +spi.write_readinto(a,b) # read gd25lq128 id +print(b) # bytearray(b'\xc8`\x18') + +a=bytes([0x90,0,0,0]) # send buff +b=bytearray(2) # receive buf +spi.write_readinto(a,b) # read gd25lq128 id +print(b) # bytearray(b'\xc8\x17') diff --git a/share/qtcreator/examples/02-Machine/timer/timer.py b/share/qtcreator/examples/02-Machine/timer/timer.py old mode 100755 new mode 100644 index a62ea128253..64e9fe74331 --- a/share/qtcreator/examples/02-Machine/timer/timer.py +++ b/share/qtcreator/examples/02-Machine/timer/timer.py @@ -1,8 +1,10 @@ -from machine import Timer - +# 基础示例 +# +# 欢迎使用CanMV IDE, 点击IDE左下角的绿色按钮开始执行脚本 -def on_timer(arg): +from machine import Timer +def on_timer(arg): #定义定时器回调函数 print("time up: %d" % arg) -tim = Timer(mode=Timer.MODE_ONE_SHOT,period=3, unit=Timer.UNIT_S, callback=on_timer, arg=1, start=True) +tim = Timer(mode=Timer.MODE_ONE_SHOT,period=3, unit=Timer.UNIT_S, callback=on_timer, arg=1, start=True) #构造定时器对象,时间为3s,默认开启定时器 diff --git a/share/qtcreator/examples/02-Machine/uart/uart.py b/share/qtcreator/examples/02-Machine/uart/uart.py new file mode 100644 index 00000000000..22f0dd3d1e5 --- /dev/null +++ b/share/qtcreator/examples/02-Machine/uart/uart.py @@ -0,0 +1,16 @@ +from machine import UART +# UART1: baudrate 115200, 8bits, parity none, one stopbits +uart = UART(UART.UART2, baudrate=115200, bits=UART.EIGHTBITS, parity=UART.PARITY_NONE, stop=UART.STOPBITS_ONE) +# UART write +r = uart.write("UART test") +print(r) +# UART read +r = uart.read() +print(r) +# UART readline +r = uart.readline() +print(r) +# UART readinto +b = bytearray(8) +r = uart.readinto(b) +print(r) diff --git a/share/qtcreator/examples/02-Machine/wdt/wdt.py b/share/qtcreator/examples/02-Machine/wdt/wdt.py old mode 100755 new mode 100644 index 759dc638bbd..1c6a656a11b --- a/share/qtcreator/examples/02-Machine/wdt/wdt.py +++ b/share/qtcreator/examples/02-Machine/wdt/wdt.py @@ -1,13 +1,17 @@ +# 基础示例 +# +# 欢迎使用CanMV IDE, 点击IDE左下角的绿色按钮开始执行脚本 + import time from machine import WDT -wdt1 = WDT(1,3) +wdt1 = WDT(1,3) #构造wdt对象,/dev/watchdog1,timeout为3s print('into', wdt1) -time.sleep(2) -print(time.ticks_ms()) +time.sleep(2) #延时2s +print(time.ticks_ms()) ## 1.test wdt feed -wdt1.feed() -time.sleep(2) +wdt1.feed() #喂狗操作 +time.sleep(2) #延时2s print(time.ticks_ms()) ## 2.test wdt stop -wdt1.stop() +wdt1.stop() #停止喂狗 diff --git a/share/qtcreator/examples/04-AI-Demo/face_detection.py b/share/qtcreator/examples/04-AI-Demo/face_detection.py old mode 100755 new mode 100644 index a0a9c3ef109..57b1c801465 --- a/share/qtcreator/examples/04-AI-Demo/face_detection.py +++ b/share/qtcreator/examples/04-AI-Demo/face_detection.py @@ -7,6 +7,7 @@ import image #图像模块,主要用于读取、图像绘制元素(框、点等)等操作 import time #时间统计 import gc #垃圾回收模块 +import os, sys #操作系统接口模块 #********************for config.py******************** # display分辨率 @@ -278,7 +279,7 @@ def media_init(): config.comm_pool[0].blk_cnt = 1 config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE - ret = media.buffer_config(config) + media.buffer_config(config) global media_source, media_sink media_source = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) @@ -286,26 +287,24 @@ def media_init(): media.create_link(media_source, media_sink) # 初始化媒体buffer - ret = media.buffer_init() - if ret: - return ret + media.buffer_init() global buffer, draw_img, osd_img buffer = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) # 用于画框 - draw_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, alloc=image.ALLOC_MPGC) + draw_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888) # 用于拷贝画框结果,防止画框过程中发生buffer搬运 osd_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, poolid=buffer.pool_id, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr) - return ret def media_deinit(): + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) # meida资源释放 global buffer,media_source, media_sink media.release_buffer(buffer) media.destroy_link(media_source, media_sink) - ret = media.buffer_deinit() - return ret + media.buffer_deinit() #********************for face_detect.py******************** @@ -318,28 +317,18 @@ def face_detect_inference(): # 显示初始化 display_init() - rgb888p_img = None # 注意:将一定要将一下过程包在try中,用于保证程序停止后,资源释放完毕;确保下次程序仍能正常运行 try: # 注意:媒体初始化(注:媒体初始化必须在camera_start之前,确保media缓冲区已配置完全) - ret = media_init() - if ret: - print("face_detect_test, buffer init failed") - return ret + media_init() # 启动camera camera_start(CAM_DEV_ID_0) - time.sleep(5) while True: + os.exitpoint() with ScopedTiming("total",1): # (1)读取一帧图像 rgb888p_img = camera_read(CAM_DEV_ID_0) - # (2)若读取失败,释放当前帧 - if rgb888p_img == -1: - print("face_detect_test, capture_image failed") - camera_release_image(CAM_DEV_ID_0,rgb888p_img) - rgb888p_img = None - continue - + # (2) # (3)若读取成功,推理当前帧 if rgb888p_img.format() == image.RGBP888: # (3.1)推理当前图像,并获取检测结果 @@ -349,17 +338,14 @@ def face_detect_inference(): # (4)释放当前帧 camera_release_image(CAM_DEV_ID_0,rgb888p_img) - rgb888p_img = None - - except Exception as e: + gc.collect() + except KeyboardInterrupt as e: + print("user stop: ", e) + except BaseException as e: + sys.print_exception(e) # 捕捉运行运行中异常,并打印错误 print(f"An error occurred during buffer used: {e}") finally: - # 释放当前帧 - if rgb888p_img is not None: - #先release掉申请的内存再stop - camera_release_image(CAM_DEV_ID_0,rgb888p_img) - # 停止camera camera_stop(CAM_DEV_ID_0) # 释放显示资源 @@ -368,15 +354,11 @@ def face_detect_inference(): kpu_deinit(kpu_face_detect) # 垃圾回收 gc.collect() - time.sleep(1) # 释放媒体资源 - ret = media_deinit() - if ret: - print("face_detect_test, buffer_deinit failed") - return ret + media_deinit() print("face_detect_test end") - return 0 if __name__ == '__main__': + os.exitpoint(os.EXITPOINT_ENABLE) face_detect_inference() diff --git a/share/qtcreator/examples/04-AI-Demo/face_landmark.py b/share/qtcreator/examples/04-AI-Demo/face_landmark.py old mode 100755 new mode 100644 index 92b929b4380..08023310f8f --- a/share/qtcreator/examples/04-AI-Demo/face_landmark.py +++ b/share/qtcreator/examples/04-AI-Demo/face_landmark.py @@ -7,7 +7,7 @@ import image # 图像模块,主要用于读取、图像绘制元素(框、点等)等操作 import time # 时间统计 import gc # 垃圾回收模块 -import os # 操作系统接口模块 +import os, sys # 操作系统接口模块 import math # 数学模块 @@ -502,7 +502,7 @@ def media_init(): config.comm_pool[0].blk_cnt = 1 config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE - ret = media.buffer_config(config) + media.buffer_config(config) global media_source, media_sink media_source = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) @@ -510,9 +510,7 @@ def media_init(): media.create_link(media_source, media_sink) # 初始化多媒体buffer - ret = media.buffer_init() - if ret: - return ret + media.buffer_init() global buffer, draw_img_ulab,draw_img, osd_img buffer = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) # 用于画框 @@ -521,16 +519,16 @@ def media_init(): # 用于拷贝画框结果,防止画框过程中发生buffer搬运 osd_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, poolid=buffer.pool_id, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr) - return ret def media_deinit(): + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) # meida资源释放 global buffer,media_source, media_sink media.release_buffer(buffer) media.destroy_link(media_source, media_sink) - ret = media.buffer_deinit() - return ret + media.buffer_deinit() #********************for face_detect.py******************** def face_landmark_inference(): @@ -544,28 +542,19 @@ def face_landmark_inference(): # 显示初始化 display_init() - rgb888p_img = None # 注意:将一定要将一下过程包在try中,用于保证程序停止后,资源释放完毕;确保下次程序仍能正常运行 try: # 注意:媒体初始化(注:媒体初始化必须在camera_start之前,确保media缓冲区已配置完全) - ret = media_init() - if ret: - print("face_detect_test, buffer init failed") - return ret + media_init() # 启动camera camera_start(CAM_DEV_ID_0) - time.sleep(5) while True: + os.exitpoint() with ScopedTiming("total",1): # (1)读取一帧图像 rgb888p_img = camera_read(CAM_DEV_ID_0) - # (2)若读取失败,释放当前帧 - if rgb888p_img == -1: - print("face_detect_test, capture_image failed") - camera_release_image(CAM_DEV_ID_0,rgb888p_img) - rgb888p_img = None - continue + # (2) # (3)若读取成功,推理当前帧 if rgb888p_img.format() == image.RGBP888: # (3.1)推理当前图像,并获取人脸检测结果 @@ -580,18 +569,14 @@ def face_landmark_inference(): # (4)释放当前帧 camera_release_image(CAM_DEV_ID_0,rgb888p_img) - rgb888p_img = None - #with ScopedTiming("gc collect", debug_mode > 0): - #gc.collect() - except Exception as e: + gc.collect() + except KeyboardInterrupt as e: + print("user stop: ", e) + except BaseException as e: + sys.print_exception(e) # 捕捉运行运行中异常,并打印错误 print(f"An error occurred during buffer used: {e}") finally: - # 释放当前帧 - if rgb888p_img is not None: - #先release掉申请的内存再stop - camera_release_image(CAM_DEV_ID_0,rgb888p_img) - # 停止camera camera_stop(CAM_DEV_ID_0) # 释放显示资源 @@ -601,15 +586,11 @@ def face_landmark_inference(): fld_kpu_deinit(kpu_face_landmark) # 垃圾回收 gc.collect() - time.sleep(1) # 释放媒体资源 - ret = media_deinit() - if ret: - print("face_landmark_test, buffer_deinit failed") - return ret + media_deinit() print("face_landmark_test end") - return 0 if __name__ == '__main__': + os.exitpoint(os.EXITPOINT_ENABLE) face_landmark_inference() diff --git a/share/qtcreator/examples/04-AI-Demo/face_mesh.py b/share/qtcreator/examples/04-AI-Demo/face_mesh.py old mode 100755 new mode 100644 index 64546e4a0ea..54e11454f0d --- a/share/qtcreator/examples/04-AI-Demo/face_mesh.py +++ b/share/qtcreator/examples/04-AI-Demo/face_mesh.py @@ -7,7 +7,7 @@ import image # 图像模块,主要用于读取、图像绘制元素(框、点等)等操作 import time # 时间统计 import gc # 垃圾回收模块 -import os # 操作系统接口模块 +import os, sys # 操作系统接口模块 import math # 数学模块 @@ -504,7 +504,7 @@ def media_init(): config.comm_pool[0].blk_cnt = 1 config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE - ret = media.buffer_config(config) + media.buffer_config(config) global media_source, media_sink media_source = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) @@ -512,9 +512,7 @@ def media_init(): media.create_link(media_source, media_sink) # 初始化多媒体buffer - ret = media.buffer_init() - if ret: - return ret + media.buffer_init() global buffer, draw_img_ulab,draw_img, osd_img buffer = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) # 用于画框 @@ -523,16 +521,16 @@ def media_init(): # 用于拷贝画框结果,防止画框过程中发生buffer搬运 osd_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, poolid=buffer.pool_id, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr) - return ret def media_deinit(): + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) # meida资源释放 global buffer,media_source, media_sink media.release_buffer(buffer) media.destroy_link(media_source, media_sink) - ret = media.buffer_deinit() - return ret + media.buffer_deinit() #********************for face_detect.py******************** def face_mesh_inference(): @@ -547,29 +545,19 @@ def face_mesh_inference(): # 显示初始化 display_init() - rgb888p_img = None # 注意:将一定要将一下过程包在try中,用于保证程序停止后,资源释放完毕;确保下次程序仍能正常运行 try: # 注意:媒体初始化(注:媒体初始化必须在camera_start之前,确保media缓冲区已配置完全) - ret = media_init() - if ret: - print("face_detect_test, buffer init failed") - return ret + media_init() # 启动camera camera_start(CAM_DEV_ID_0) - time.sleep(5) while True: + os.exitpoint() with ScopedTiming("total",1): # (1)读取一帧图像 rgb888p_img = camera_read(CAM_DEV_ID_0) - # (2)若读取失败,释放当前帧 - if rgb888p_img == -1: - print("face_detect_test, capture_image failed") - camera_release_image(CAM_DEV_ID_0,rgb888p_img) - rgb888p_img = None - continue - # (3)若读取成功,推理当前帧 + # (2) # (3)若读取成功,推理当前帧 if rgb888p_img.format() == image.RGBP888: # (3.1)推理当前图像,并获取人脸检测结果 dets = fd_kpu_run(kpu_face_detect,rgb888p_img) @@ -585,18 +573,14 @@ def face_mesh_inference(): # (4)释放当前帧 camera_release_image(CAM_DEV_ID_0,rgb888p_img) - rgb888p_img = None - #with ScopedTiming("gc collect", debug_mode > 0): - #gc.collect() - except Exception as e: + gc.collect() + except KeyboardInterrupt as e: + print("user stop: ", e) + except BaseException as e: + sys.print_exception(e) # 捕捉运行运行中异常,并打印错误 print(f"An error occurred during buffer used: {e}") finally: - # 释放当前帧 - if rgb888p_img is not None: - #先release掉申请的内存再stop - camera_release_image(CAM_DEV_ID_0,rgb888p_img) - # 停止camera camera_stop(CAM_DEV_ID_0) # 释放显示资源 @@ -607,15 +591,11 @@ def face_mesh_inference(): fmpost_kpu_deinit(kpu_face_mesh_post) # 垃圾回收 gc.collect() - time.sleep(1) # 释放媒体资源 - ret = media_deinit() - if ret: - print("face_mesh_test, buffer_deinit failed") - return ret + media_deinit() - #print("face_mesh_test end") - return 0 + print("face_mesh_test end") if __name__ == '__main__': + os.exitpoint(os.EXITPOINT_ENABLE) face_mesh_inference() diff --git a/share/qtcreator/examples/04-AI-Demo/face_parse.py b/share/qtcreator/examples/04-AI-Demo/face_parse.py old mode 100755 new mode 100644 index b3b982b33b2..10d3ecc618c --- a/share/qtcreator/examples/04-AI-Demo/face_parse.py +++ b/share/qtcreator/examples/04-AI-Demo/face_parse.py @@ -7,7 +7,7 @@ import image # 图像模块,主要用于读取、图像绘制元素(框、点等)等操作 import time # 时间统计 import gc # 垃圾回收模块 -import os # 操作系统接口模块 +import os, sys # 操作系统接口模块 import math # 数学模块 #********************for config.py******************** @@ -415,7 +415,7 @@ def media_init(): config.comm_pool[0].blk_cnt = 1 config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE - ret = media.buffer_config(config) + media.buffer_config(config) global media_source, media_sink media_source = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) @@ -423,9 +423,7 @@ def media_init(): media.create_link(media_source, media_sink) # 初始化多媒体buffer - ret = media.buffer_init() - if ret: - return ret + media.buffer_init() global buffer, draw_img_ulab,draw_img, osd_img buffer = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) @@ -435,16 +433,16 @@ def media_init(): # 用于拷贝画框结果,防止画框过程中发生buffer搬运 osd_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, poolid=buffer.pool_id, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr) - return ret def media_deinit(): + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) # meida资源释放 global buffer,media_source, media_sink media.release_buffer(buffer) media.destroy_link(media_source, media_sink) - ret = media.buffer_deinit() - return ret + media.buffer_deinit() #********************for face_detect.py******************** def face_parse_inference(): @@ -458,31 +456,20 @@ def face_parse_inference(): # 显示初始化 display_init() - rgb888p_img = None # 注意:将一定要将一下过程包在try中,用于保证程序停止后,资源释放完毕;确保下次程序仍能正常运行 try: # 注意:媒体初始化(注:媒体初始化必须在camera_start之前,确保media缓冲区已配置完全) - ret = media_init() - if ret: - print("face_detect_test, buffer init failed") - return ret + media_init() # 启动camera camera_start(CAM_DEV_ID_0) - time.sleep(5) - gc_count = 0 while True: + os.exitpoint() with ScopedTiming("total",1): # (1)读取一帧图像 rgb888p_img = camera_read(CAM_DEV_ID_0) - # (2)若读取失败,释放当前帧 - if rgb888p_img == -1: - print("face_detect_test, capture_image failed") - camera_release_image(CAM_DEV_ID_0,rgb888p_img) - rgb888p_img = None - continue - + # (2) # (3)若读取成功,推理当前帧 if rgb888p_img.format() == image.RGBP888: # (3.1)推理当前图像,并获取人脸检测结果 @@ -497,16 +484,14 @@ def face_parse_inference(): # (4)释放当前帧 camera_release_image(CAM_DEV_ID_0,rgb888p_img) - rgb888p_img = None - except Exception as e: + gc.collect() + except KeyboardInterrupt as e: + print("user stop: ", e) + except BaseException as e: + sys.print_exception(e) # 捕捉运行运行中异常,并打印错误 print(f"An error occurred during buffer used: {e}") finally: - # 释放当前帧 - if rgb888p_img is not None: - #先release掉申请的内存再stop - camera_release_image(CAM_DEV_ID_0,rgb888p_img) - # 停止camera camera_stop(CAM_DEV_ID_0) # 释放显示资源 @@ -516,15 +501,11 @@ def face_parse_inference(): fp_kpu_deinit(kpu_face_parse) # 垃圾回收 gc.collect() - time.sleep(1) # 释放媒体资源 - ret = media_deinit() - if ret: - print("face_parse_test, buffer_deinit failed") - return ret + media_deinit() print("face_parse_test end") - return 0 if __name__ == '__main__': + os.exitpoint(os.EXITPOINT_ENABLE) face_parse_inference() diff --git a/share/qtcreator/examples/04-AI-Demo/face_pose.py b/share/qtcreator/examples/04-AI-Demo/face_pose.py old mode 100755 new mode 100644 index aff7dd1e356..1ee888c0d67 --- a/share/qtcreator/examples/04-AI-Demo/face_pose.py +++ b/share/qtcreator/examples/04-AI-Demo/face_pose.py @@ -7,7 +7,7 @@ import image # 图像模块,主要用于读取、图像绘制元素(框、点等)等操作 import time # 时间统计 import gc # 垃圾回收模块 -import os # 操作系统接口模块 +import os, sys # 操作系统接口模块 import math # 数学模块 #********************for config.py******************** @@ -500,7 +500,7 @@ def media_init(): config.comm_pool[0].blk_cnt = 1 config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE - ret = media.buffer_config(config) + media.buffer_config(config) global media_source, media_sink media_source = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) @@ -508,9 +508,7 @@ def media_init(): media.create_link(media_source, media_sink) # 初始化多媒体buffer - ret = media.buffer_init() - if ret: - return ret + media.buffer_init() global buffer, draw_img_ulab,draw_img, osd_img buffer = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) # 用于画框,draw_img->draw_img_ulab(两者指向同一块内存) @@ -519,16 +517,16 @@ def media_init(): # 用于拷贝画框结果,防止画框过程中发生buffer搬运 osd_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, poolid=buffer.pool_id, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr) - return ret def media_deinit(): + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) # meida资源释放 global buffer,media_source, media_sink media.release_buffer(buffer) media.destroy_link(media_source, media_sink) - ret = media.buffer_deinit() - return ret + media.buffer_deinit() #********************for face_detect.py******************** def face_pose_inference(): @@ -542,31 +540,20 @@ def face_pose_inference(): # 显示初始化 display_init() - rgb888p_img = None # 注意:将一定要将一下过程包在try中,用于保证程序停止后,资源释放完毕;确保下次程序仍能正常运行 try: # 注意:媒体初始化(注:媒体初始化必须在camera_start之前,确保media缓冲区已配置完全) - ret = media_init() - if ret: - print("face_detect_test, buffer init failed") - return ret + media_init() # 启动camera camera_start(CAM_DEV_ID_0) - time.sleep(5) - gc_count = 0 while True: + os.exitpoint() with ScopedTiming("total",1): # (1)读取一帧图像 rgb888p_img = camera_read(CAM_DEV_ID_0) - # (2)若读取失败,释放当前帧 - if rgb888p_img == -1: - print("face_detect_test, capture_image failed") - camera_release_image(CAM_DEV_ID_0,rgb888p_img) - rgb888p_img = None - continue - + # (2) # (3)若读取成功,推理当前帧 if rgb888p_img.format() == image.RGBP888: # (3.1)推理当前图像,并获取人脸检测结果 @@ -581,16 +568,14 @@ def face_pose_inference(): # (4)释放当前帧 camera_release_image(CAM_DEV_ID_0,rgb888p_img) - rgb888p_img = None - - except Exception as e: + gc.collect() + except KeyboardInterrupt as e: + print("user stop: ", e) + except BaseException as e: + sys.print_exception(e) # 捕捉运行运行中异常,并打印错误 print(f"An error occurred during buffer used: {e}") finally: - # 释放当前帧 - if rgb888p_img is not None: - #先release掉申请的内存再stop - camera_release_image(CAM_DEV_ID_0,rgb888p_img) # 停止camera camera_stop(CAM_DEV_ID_0) # 释放显示资源 @@ -600,15 +585,11 @@ def face_pose_inference(): fp_kpu_deinit(kpu_face_pose) # 垃圾回收 gc.collect() - time.sleep(1) # 释放媒体资源 - ret = media_deinit() - if ret: - print("face_pose_test, buffer_deinit failed") - return ret + media_deinit() print("face_pose_test end") - return 0 if __name__ == '__main__': + os.exitpoint(os.EXITPOINT_ENABLE) face_pose_inference() diff --git a/share/qtcreator/examples/04-AI-Demo/face_recognition.py b/share/qtcreator/examples/04-AI-Demo/face_recognition.py old mode 100755 new mode 100644 index 0afd17f92ac..3f00be7f76e --- a/share/qtcreator/examples/04-AI-Demo/face_recognition.py +++ b/share/qtcreator/examples/04-AI-Demo/face_recognition.py @@ -7,7 +7,7 @@ import image # 图像模块,主要用于读取、图像绘制元素(框、点等)等操作 import time # 时间统计 import gc # 垃圾回收模块 -import os # 操作系统接口模块 +import os, sys # 操作系统接口模块 import math # 数学模块 #********************for config.py******************** @@ -585,7 +585,7 @@ def media_init(): config.comm_pool[0].blk_cnt = 1 config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE - ret = media.buffer_config(config) + media.buffer_config(config) global media_source, media_sink media_source = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) @@ -593,26 +593,24 @@ def media_init(): media.create_link(media_source, media_sink) # 初始化多媒体buffer - ret = media.buffer_init() - if ret: - return ret + media.buffer_init() global buffer, draw_img, osd_img buffer = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) # 用于画框 - draw_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, alloc=image.ALLOC_MPGC) + draw_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888) # 用于拷贝画框结果,防止画框过程中发生buffer搬运 osd_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, poolid=buffer.pool_id, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr) - return ret def media_deinit(): + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) # meida资源释放 global buffer,media_source, media_sink media.release_buffer(buffer) media.destroy_link(media_source, media_sink) - ret = media.buffer_deinit() - return ret + media.buffer_deinit() #********************for face_detect.py******************** def face_recognition_inference(): @@ -626,29 +624,19 @@ def face_recognition_inference(): # 显示初始化 display_init() - rgb888p_img = None # 注意:将一定要将一下过程包在try中,用于保证程序停止后,资源释放完毕;确保下次程序仍能正常运行 try: # 注意:媒体初始化(注:媒体初始化必须在camera_start之前,确保media缓冲区已配置完全) - ret = media_init() - if ret: - print("face_detect_test, buffer init failed") - return ret + media_init() # 启动camera camera_start(CAM_DEV_ID_0) - time.sleep(5) while True: + os.exitpoint() with ScopedTiming("total",1): # (1)读取一帧图像 rgb888p_img = camera_read(CAM_DEV_ID_0) - # (2)若读取失败,释放当前帧 - if rgb888p_img == -1: - print("face_detect_test, capture_image failed") - camera_release_image(CAM_DEV_ID_0,rgb888p_img) - rgb888p_img = None - continue - + # (2) # (3)若读取成功,推理当前帧 if rgb888p_img.format() == image.RGBP888: # (3.1)推理当前图像,并获取人脸检测结果 @@ -663,17 +651,14 @@ def face_recognition_inference(): # (4)释放当前帧 camera_release_image(CAM_DEV_ID_0,rgb888p_img) - rgb888p_img = None gc.collect() - except Exception as e: + except KeyboardInterrupt as e: + print("user stop: ", e) + except BaseException as e: + sys.print_exception(e) # 捕捉运行运行中异常,并打印错误 print(f"An error occurred during buffer used: {e}") finally: - # 释放当前帧 - if rgb888p_img is not None: - #先release掉申请的内存再stop - camera_release_image(CAM_DEV_ID_0,rgb888p_img) - # 停止camera camera_stop(CAM_DEV_ID_0) # 释放显示资源 @@ -683,15 +668,11 @@ def face_recognition_inference(): fr_kpu_deinit(kpu_face_recg) # 垃圾回收 gc.collect() - time.sleep(1) # 释放媒体资源 - ret = media_deinit() - if ret: - print("face_recognition_test, buffer_deinit failed") - return ret + media_deinit() print("face_recognition_test end") - return 0 if __name__ == '__main__': + os.exitpoint(os.EXITPOINT_ENABLE) face_recognition_inference() diff --git a/share/qtcreator/examples/04-AI-Demo/face_registration.py b/share/qtcreator/examples/04-AI-Demo/face_registration.py old mode 100755 new mode 100644 index 301aba5fe43..55366a6e416 --- a/share/qtcreator/examples/04-AI-Demo/face_registration.py +++ b/share/qtcreator/examples/04-AI-Demo/face_registration.py @@ -4,7 +4,7 @@ import image #图像模块,主要用于读取、图像绘制元素(框、点等)等操作 import time #时间统计 import gc #垃圾回收模块 -import os #操作系统接口模块 +import os, sys #操作系统接口模块 import math #数学模块 #********************for config.py******************** @@ -462,7 +462,10 @@ def face_registration_inference(): print('No person detected') gc.collect() - except Exception as e: + except KeyboardInterrupt as e: + print("user stop: ", e) + except BaseException as e: + sys.print_exception(e) print(f"An error occurred during buffer used: {e}") finally: # 释放kpu资源 @@ -470,10 +473,9 @@ def face_registration_inference(): fr_kpu_deinit(kpu_face_reg) # 垃圾回收 gc.collect() - time.sleep(1) print("face_registration_test end") - return 0 if __name__ == '__main__': + os.exitpoint(os.EXITPOINT_ENABLE) face_registration_inference() diff --git a/share/qtcreator/examples/04-AI-Demo/finger_guessing.py b/share/qtcreator/examples/04-AI-Demo/finger_guessing.py old mode 100755 new mode 100644 index e0723c6cd20..b2e41c386f3 --- a/share/qtcreator/examples/04-AI-Demo/finger_guessing.py +++ b/share/qtcreator/examples/04-AI-Demo/finger_guessing.py @@ -8,6 +8,7 @@ import time #时间统计 import gc #垃圾回收模块 import aicube #aicube模块,封装ai cube 相关后处理 +import os, sys #操作系统接口模块 ##config.py #display分辨率 @@ -420,7 +421,7 @@ def media_init(): config.comm_pool[0].blk_cnt = 1 config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE - ret = media.buffer_config(config) + media.buffer_config(config) global media_source, media_sink media_source = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) @@ -428,9 +429,7 @@ def media_init(): media.create_link(media_source, media_sink) # 初始化多媒体buffer - ret = media.buffer_init() - if ret: - return ret + media.buffer_init() global buffer, draw_img, osd_img, masks buffer = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) # 图层1,用于画框 @@ -439,16 +438,16 @@ def media_init(): # 图层2,用于拷贝画框结果,防止画框过程中发生buffer搬运 osd_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, poolid=buffer.pool_id, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr) - return ret # media 释放内存 def media_deinit(): + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) global buffer,media_source, media_sink media.release_buffer(buffer) media.destroy_link(media_source, media_sink) - ret = media.buffer_deinit() - return ret + media.buffer_deinit() #**********for finger_guessing.py********** @@ -459,13 +458,8 @@ def finger_guessing_inference(): camera_init(CAM_DEV_ID_0) # 初始化 camera display_init() # 初始化 display - rgb888p_img = None try: - ret = media_init() - if ret: - print("finger_guessing, buffer init failed") - return ret - + media_init() camera_start(CAM_DEV_ID_0) # 开启 camera counts_guess = -1 # 猜拳次数 计数 player_win = 0 # 玩家 赢次计数 @@ -475,14 +469,9 @@ def finger_guessing_inference(): LIBRARY = ["fist","yeah","five"] # 猜拳 石头剪刀布 三种方案的dict while True: + os.exitpoint() with ScopedTiming("total",1): rgb888p_img = camera_read(CAM_DEV_ID_0) # 读取一帧图像 - if rgb888p_img == -1: - print("finger_guessing, capture_image failed") - camera_release_image(CAM_DEV_ID_0,rgb888p_img) - rgb888p_img = None - continue - # for rgb888planar if rgb888p_img.format() == image.RGBP888: with ScopedTiming("trigger time", debug_mode > 0): @@ -491,6 +480,7 @@ def finger_guessing_inference(): draw_img.clear() for det_box in dets: gesture = hk_gesture(kpu_hand_keypoint_detect,rgb888p_img,det_box) # 执行手掌关键点检测 kpu 运行 以及 后处理过程 得到手势类型 + camera_release_image(CAM_DEV_ID_0,rgb888p_img) # camera 释放图形 if (len(dets) >= 2): draw_img.draw_string( 300 , 500, "Must have one hand !", color=(255,255,0,0), scale=7) draw_img.copy_to(osd_img) @@ -572,31 +562,25 @@ def finger_guessing_inference(): else: draw_img.copy_to(osd_img) display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD3) # 将得到的图像 绘制到 display - - camera_release_image(CAM_DEV_ID_0,rgb888p_img) # camera 释放图形 - rgb888p_img = None + else: + camera_release_image(CAM_DEV_ID_0,rgb888p_img) # camera 释放图形 gc.collect() - except Exception as e: + except KeyboardInterrupt as e: + print("user stop: ", e) + except BaseException as e: + sys.print_exception(e) print(f"An error occurred during buffer used: {e}") finally: - if rgb888p_img is not None: - #先release掉申请的内存再stop - camera_release_image(CAM_DEV_ID_0,rgb888p_img) - camera_stop(CAM_DEV_ID_0) # 停止 camera display_deinit() # 停止 display hd_kpu_deinit(kpu_hand_detect) # 释放手掌检测 kpu hk_kpu_deinit(kpu_hand_keypoint_detect) # 释放手掌关键点检测 kpu gc.collect() - ret = media_deinit() # 释放 整个 media - if ret: - print("finger_guessing, buffer_deinit failed") - return ret + media_deinit() # 释放 整个 media print("finger_guessing_test end") - return 0 if __name__ == '__main__': + os.exitpoint(os.EXITPOINT_ENABLE) finger_guessing_inference() - diff --git a/share/qtcreator/examples/04-AI-Demo/hand_detection.py b/share/qtcreator/examples/04-AI-Demo/hand_detection.py old mode 100755 new mode 100644 index 9ca1d45da2c..7fb6b1fd448 --- a/share/qtcreator/examples/04-AI-Demo/hand_detection.py +++ b/share/qtcreator/examples/04-AI-Demo/hand_detection.py @@ -8,7 +8,7 @@ import time #时间统计 import image #图像模块,主要用于读取、图像绘制元素(框、点等)等操作 - +import os, sys #操作系统接口模块 import gc #垃圾回收模块 ##config.py @@ -254,7 +254,7 @@ def media_init(): config.comm_pool[0].blk_cnt = 1 config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE - ret = media.buffer_config(config) + media.buffer_config(config) global media_source, media_sink media_source = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) @@ -262,26 +262,24 @@ def media_init(): media.create_link(media_source, media_sink) # 初始化多媒体buffer - ret = media.buffer_init() - if ret: - return ret + media.buffer_init() global buffer, draw_img, osd_img buffer = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) # 图层1,用于画框 - draw_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, alloc=image.ALLOC_MPGC) + draw_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888) # 图层2,用于拷贝画框结果,防止画框过程中发生buffer搬运 osd_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, poolid=buffer.pool_id, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr) - return ret # media 释放内存 def media_deinit(): + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) global buffer,media_source, media_sink media.release_buffer(buffer) media.destroy_link(media_source, media_sink) - ret = media.buffer_deinit() - return ret + media.buffer_deinit() #**********for hand_detect.py********** def hand_detect_inference(): @@ -290,22 +288,14 @@ def hand_detect_inference(): camera_init(CAM_DEV_ID_0) # 初始化 camera display_init() # 初始化 display - rgb888p_img = None try: - ret = media_init() - if ret: - print("hand_detect_test, buffer init failed") - return ret + media_init() camera_start(CAM_DEV_ID_0) while True: + os.exitpoint() with ScopedTiming("total",1): rgb888p_img = camera_read(CAM_DEV_ID_0) # 读取一帧图片 - if rgb888p_img == -1: - print("hand_detect_test, capture_image failed") - camera_release_image(CAM_DEV_ID_0,rgb888p_img) - rgb888p_img = None - continue # for rgb888planar if rgb888p_img.format() == image.RGBP888: @@ -313,27 +303,21 @@ def hand_detect_inference(): display_draw(dets) # 将得到的检测结果 绘制到 display camera_release_image(CAM_DEV_ID_0,rgb888p_img) # camera 释放图像 - rgb888p_img = None - #gc.collect() - except Exception as e: + gc.collect() + except KeyboardInterrupt as e: + print("user stop: ", e) + except BaseException as e: + sys.print_exception(e) print(f"An error occurred during buffer used: {e}") finally: - if rgb888p_img is not None: - #先release掉申请的内存再stop - camera_release_image(CAM_DEV_ID_0,rgb888p_img) - camera_stop(CAM_DEV_ID_0) # 停止 camera display_deinit() # 释放 display kpu_deinit(kpu_hand_detect) # 释放 kpu gc.collect() - ret = media_deinit() # 释放 整个media - if ret: - print("hand_detect_test, buffer_deinit failed") - return ret + media_deinit() # 释放 整个media print("hand_detect_test end") - return 0 if __name__ == '__main__': + os.exitpoint(os.EXITPOINT_ENABLE) hand_detect_inference() - diff --git a/share/qtcreator/examples/04-AI-Demo/hand_keypoint_detection.py b/share/qtcreator/examples/04-AI-Demo/hand_keypoint_detection.py old mode 100755 new mode 100644 index c01e33028e9..5b9490c5a1a --- a/share/qtcreator/examples/04-AI-Demo/hand_keypoint_detection.py +++ b/share/qtcreator/examples/04-AI-Demo/hand_keypoint_detection.py @@ -8,7 +8,7 @@ import time #时间统计 import image #图像模块,主要用于读取、图像绘制元素(框、点等)等操作 - +import os, sys #操作系统接口模块 import gc #垃圾回收模块 ##config.py @@ -349,7 +349,7 @@ def media_init(): config.comm_pool[0].blk_cnt = 1 config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE - ret = media.buffer_config(config) + media.buffer_config(config) global media_source, media_sink media_source = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) @@ -357,26 +357,24 @@ def media_init(): media.create_link(media_source, media_sink) # 初始化多媒体buffer - ret = media.buffer_init() - if ret: - return ret + media.buffer_init() global buffer, draw_img, osd_img buffer = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) # 图层1,用于画框 - draw_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, alloc=image.ALLOC_MPGC) + draw_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888) # 图层2,用于拷贝画框结果,防止画框过程中发生buffer搬运 osd_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, poolid=buffer.pool_id, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr) - return ret # media 释放内存 def media_deinit(): + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) global buffer,media_source, media_sink media.release_buffer(buffer) media.destroy_link(media_source, media_sink) - ret = media.buffer_deinit() - return ret + media.buffer_deinit() #**********for hand_keypoint_detect.py********** def hand_keypoint_detect_inference(): @@ -386,23 +384,13 @@ def hand_keypoint_detect_inference(): camera_init(CAM_DEV_ID_0) # 初始化 camera display_init() # 初始化 display - rgb888p_img = None try: - ret = media_init() - if ret: - print("hand_detect_test, buffer init failed") - return ret - + media_init() camera_start(CAM_DEV_ID_0) while True: + os.exitpoint() with ScopedTiming("total",1): rgb888p_img = camera_read(CAM_DEV_ID_0) # 读取一帧图片 - if rgb888p_img == -1: - print("hand_detect_test, capture_image failed") - camera_release_image(CAM_DEV_ID_0,rgb888p_img) - rgb888p_img = None - continue - # for rgb888planar if rgb888p_img.format() == image.RGBP888: dets = hd_kpu_run(kpu_hand_detect,rgb888p_img) # 执行手掌检测 kpu 运行 以及 后处理过程 @@ -443,29 +431,24 @@ def hand_keypoint_detect_inference(): display_draw(hk_results[0], x1_kp, y1_kp, w_kp, h_kp) # 将得到的手掌关键点检测结果 绘制到 display camera_release_image(CAM_DEV_ID_0,rgb888p_img) # camera 释放图像 - rgb888p_img = None - #gc.collect() + gc.collect() draw_img.copy_to(osd_img) display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD3) - except Exception as e: + except KeyboardInterrupt as e: + print("user stop: ", e) + except BaseException as e: + sys.print_exception(e) print(f"An error occurred during buffer used: {e}") finally: - if rgb888p_img is not None: - #先release掉申请的内存再stop - camera_release_image(CAM_DEV_ID_0,rgb888p_img) - camera_stop(CAM_DEV_ID_0) # 停止 camera display_deinit() # 释放 display hd_kpu_deinit(kpu_hand_detect) # 释放手掌检测 kpu hk_kpu_deinit(kpu_hand_keypoint_detect) # 释放手掌关键点检测 kpu gc.collect() - ret = media_deinit() # 释放 整个media - if ret: - print("hand_detect_test, buffer_deinit failed") - return ret + media_deinit() # 释放 整个media print("hand_detect_test end") - return 0 if __name__ == '__main__': + os.exitpoint(os.EXITPOINT_ENABLE) hand_keypoint_detect_inference() diff --git a/share/qtcreator/examples/04-AI-Demo/hand_recognition.py b/share/qtcreator/examples/04-AI-Demo/hand_recognition.py old mode 100755 new mode 100644 index 6fb4c7371e5..4441e4beed5 --- a/share/qtcreator/examples/04-AI-Demo/hand_recognition.py +++ b/share/qtcreator/examples/04-AI-Demo/hand_recognition.py @@ -8,7 +8,7 @@ import time #时间统计 import image #图像模块,主要用于读取、图像绘制元素(框、点等)等操作 - +import os, sys #操作系统接口模块 import gc #垃圾回收模块 ##config.py @@ -338,7 +338,7 @@ def media_init(): config.comm_pool[0].blk_cnt = 1 config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE - ret = media.buffer_config(config) + media.buffer_config(config) global media_source, media_sink media_source = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) @@ -346,26 +346,24 @@ def media_init(): media.create_link(media_source, media_sink) # 初始化多媒体buffer - ret = media.buffer_init() - if ret: - return ret + media.buffer_init() global buffer, draw_img, osd_img buffer = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) # 图层1,用于画框 - draw_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, alloc=image.ALLOC_MPGC) + draw_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888) # 图层2,用于拷贝画框结果,防止画框过程中发生buffer搬运 osd_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, poolid=buffer.pool_id, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr) - return ret # media 释放内存 def media_deinit(): + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) global buffer,media_source, media_sink media.release_buffer(buffer) media.destroy_link(media_source, media_sink) - ret = media.buffer_deinit() - return ret + media.buffer_deinit() #**********for hand_recognition.py********** def hand_recognition_inference(): @@ -375,23 +373,13 @@ def hand_recognition_inference(): camera_init(CAM_DEV_ID_0) # 初始化 camera display_init() # 初始化 display - rgb888p_img = None try: - ret = media_init() - if ret: - print("hand_recognition_test, buffer init failed") - return ret - + media_init() camera_start(CAM_DEV_ID_0) while True: + os.exitpoint() with ScopedTiming("total",1): rgb888p_img = camera_read(CAM_DEV_ID_0) # 读取一帧图片 - if rgb888p_img == -1: - print("hand_recognition_test, capture_image failed") - camera_release_image(CAM_DEV_ID_0,rgb888p_img) - rgb888p_img = None - continue - # for rgb888planar if rgb888p_img.format() == image.RGBP888: dets = hd_kpu_run(kpu_hand_detect,rgb888p_img) # 执行手掌检测 kpu 运行 以及 后处理过程 @@ -432,29 +420,24 @@ def hand_recognition_inference(): draw_img.draw_string( x1 , y1-50, hr_results, color=(255,0, 255, 0), scale=4) # 将得到的识别结果 绘制到 display camera_release_image(CAM_DEV_ID_0,rgb888p_img) # camera 释放图像 - rgb888p_img = None - #gc.collect() + gc.collect() draw_img.copy_to(osd_img) display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD3) - except Exception as e: + except KeyboardInterrupt as e: + print("user stop: ", e) + except BaseException as e: + sys.print_exception(e) print(f"An error occurred during buffer used: {e}") finally: - if rgb888p_img is not None: - #先release掉申请的内存再stop - camera_release_image(CAM_DEV_ID_0,rgb888p_img) - camera_stop(CAM_DEV_ID_0) # 停止 camera display_deinit() # 释放 display hd_kpu_deinit(kpu_hand_detect) # 释放手掌检测 kpu hr_kpu_deinit(kpu_hand_recognition) # 释放手势识别 kpu gc.collect() - ret = media_deinit() # 释放 整个media - if ret: - print("hand_recognition_test, buffer_deinit failed") - return ret + media_deinit() # 释放 整个media print("hand_recognition_test end") - return 0 if __name__ == '__main__': + os.exitpoint(os.EXITPOINT_ENABLE) hand_recognition_inference() diff --git a/share/qtcreator/examples/04-AI-Demo/keyword_spotting.py b/share/qtcreator/examples/04-AI-Demo/keyword_spotting.py old mode 100755 new mode 100644 index 416cac81ee3..c8d6293a2b9 --- a/share/qtcreator/examples/04-AI-Demo/keyword_spotting.py +++ b/share/qtcreator/examples/04-AI-Demo/keyword_spotting.py @@ -7,7 +7,7 @@ import time # 时间统计 import struct # 字节字符转换模块 import gc # 垃圾回收模块 -import os # 操作系统接口模块 +import os, sys # 操作系统接口模块 # key word spotting任务 # 检测阈值 @@ -55,9 +55,7 @@ def init_kws(): # 初始化音频流 p = PyAudio() p.initialize(CHUNK) - ret = media.buffer_init() - if ret: - print("record_audio, buffer_init failed") + media.buffer_init() # 用于采集实时音频数据 input_stream = p.open( format=FORMAT, @@ -142,6 +140,7 @@ def kws_inference(): pcm_data_list = [] try: while True: + os.exitpoint() with ScopedTiming("total", 1): pcm_data_list.clear() # 对实时音频流进行推理 @@ -154,6 +153,12 @@ def kws_inference(): pcm_data_list.append(float_pcm_data) # kpu运行和后处理 kpu_run_kws(kpu_kws,pcm_data_list) + gc.collect() + except KeyboardInterrupt as e: + print("user stop: ", e) + except BaseException as e: + sys.print_exception(e) + print(f"An error occurred during buffer used: {e}") finally: input_stream.stop_stream() output_stream.stop_stream() @@ -162,7 +167,7 @@ def kws_inference(): p.terminate() media.buffer_deinit() aidemo.kws_fp_destroy(fp) - #gc.collect() if __name__=="__main__": + os.exitpoint(os.EXITPOINT_ENABLE) kws_inference() diff --git a/share/qtcreator/examples/04-AI-Demo/licence_det.py b/share/qtcreator/examples/04-AI-Demo/licence_det.py old mode 100755 new mode 100644 index 82bc51ef74d..16c7fa67428 --- a/share/qtcreator/examples/04-AI-Demo/licence_det.py +++ b/share/qtcreator/examples/04-AI-Demo/licence_det.py @@ -7,6 +7,7 @@ import time #时间统计 import gc #垃圾回收模块 import aidemo #aidemo模块,封装ai demo相关后处理、画图操作 +import os, sys #操作系统接口模块 ##config.py #display分辨率 @@ -220,7 +221,7 @@ def media_init(): config.comm_pool[0].blk_cnt = 1 config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE - ret = media.buffer_config(config) + media.buffer_config(config) global media_source, media_sink media_source = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) @@ -228,26 +229,24 @@ def media_init(): media.create_link(media_source, media_sink) # 初始化多媒体buffer - ret = media.buffer_init() - if ret: - return ret + media.buffer_init() global buffer, draw_img, osd_img buffer = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) # 图层1,用于画框 - draw_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, alloc=image.ALLOC_MPGC) + draw_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888) # 图层2,用于拷贝画框结果,防止画框过程中发生buffer搬运 osd_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, poolid=buffer.pool_id, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr) - return ret # media 释放内存 def media_deinit(): + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) global buffer,media_source, media_sink media.release_buffer(buffer) media.destroy_link(media_source, media_sink) - ret = media.buffer_deinit() - return ret + media.buffer_deinit() #**********for licence_det.py********** @@ -257,53 +256,34 @@ def licence_det_inference(): camera_init(CAM_DEV_ID_0) # 初始化 camera display_init() # 初始化 display - rgb888p_img = None try: - ret = media_init() - if ret: - print("licence_det, buffer init failed") - return ret - + media_init() camera_start(CAM_DEV_ID_0) - time.sleep(5) while True: + os.exitpoint() with ScopedTiming("total",1): rgb888p_img = camera_read(CAM_DEV_ID_0) # 读取一帧图片 - if rgb888p_img == -1: - print("licence_det, capture_image failed") - camera_release_image(CAM_DEV_ID_0,rgb888p_img) - rgb888p_img = None - continue - # for rgb888planar if rgb888p_img.format() == image.RGBP888: dets = kpu_run(kpu_licence_det,rgb888p_img) # 执行车牌检测 kpu 运行 以及后处理过程 display_draw(dets) # 将得到的 检测结果 绘制到 display camera_release_image(CAM_DEV_ID_0,rgb888p_img) # camera 释放图像 - rgb888p_img = None - # gc.collect() - except Exception as e: + gc.collect() + except KeyboardInterrupt as e: + print("user stop: ", e) + except BaseException as e: + sys.print_exception(e) print(f"An error occurred during buffer used: {e}") finally: - if rgb888p_img is not None: - #先release掉申请的内存再stop - camera_release_image(CAM_DEV_ID_0,rgb888p_img) - camera_stop(CAM_DEV_ID_0) # 停止 camera display_deinit() # 释放 display kpu_deinit(kpu_licence_det) # 释放 kpu gc.collect() - time.sleep(1) - ret = media_deinit() # 释放整个media - if ret: - print("licence_det, buffer_deinit failed") - return ret + media_deinit() # 释放整个media print("licence_det end") - return 0 if __name__ == '__main__': + os.exitpoint(os.EXITPOINT_ENABLE) licence_det_inference() - - diff --git a/share/qtcreator/examples/04-AI-Demo/licence_det_rec.py b/share/qtcreator/examples/04-AI-Demo/licence_det_rec.py old mode 100755 new mode 100644 index 16540844cdc..ff6d08c6a21 --- a/share/qtcreator/examples/04-AI-Demo/licence_det_rec.py +++ b/share/qtcreator/examples/04-AI-Demo/licence_det_rec.py @@ -7,6 +7,7 @@ import time #时间统计 import gc #垃圾回收模块 import aidemo #aidemo模块,封装ai demo相关后处理、画图操作 +import os, sys #操作系统接口模块 ##config.py #display分辨率 @@ -353,7 +354,7 @@ def media_init(): config.comm_pool[0].blk_cnt = 1 config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE - ret = media.buffer_config(config) + media.buffer_config(config) global media_source, media_sink media_source = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) @@ -361,26 +362,24 @@ def media_init(): media.create_link(media_source, media_sink) # 初始化多媒体buffer - ret = media.buffer_init() - if ret: - return ret + media.buffer_init() global buffer, draw_img, osd_img buffer = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) # 图层1,用于画框 - draw_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, alloc=image.ALLOC_MPGC) + draw_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888) # 图层2,用于拷贝画框结果,防止画框过程中发生buffer搬运 osd_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, poolid=buffer.pool_id, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr) - return ret # media 释放内存 def media_deinit(): + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) global buffer,media_source, media_sink media.release_buffer(buffer) media.destroy_link(media_source, media_sink) - ret = media.buffer_deinit() - return ret + media.buffer_deinit() #**********for licence_det_rec.py********** @@ -391,24 +390,13 @@ def licence_det_rec_inference(): camera_init(CAM_DEV_ID_0) # 初始化 camera display_init() # 初始化 display - rgb888p_img = None try: - ret = media_init() - if ret: - print("licence_det_rec, buffer init failed") - return ret - + media_init() camera_start(CAM_DEV_ID_0) - time.sleep(5) while True: + os.exitpoint() with ScopedTiming("total",1): rgb888p_img = camera_read(CAM_DEV_ID_0) # 读取一帧图片 - if rgb888p_img == -1: - print("licence_det_rec, capture_image failed") - camera_release_image(CAM_DEV_ID_0,rgb888p_img) - rgb888p_img = None - continue - # for rgb888planar if rgb888p_img.format() == image.RGBP888: dets = det_kpu_run(kpu_licence_det,rgb888p_img) # 执行车牌检测 kpu 运行 以及 后处理过程 @@ -416,30 +404,22 @@ def licence_det_rec_inference(): display_draw(dets_recs) # 将得到的检测结果和识别结果 绘制到display camera_release_image(CAM_DEV_ID_0,rgb888p_img) # camera 释放图像 - rgb888p_img = None - # gc.collect() - except Exception as e: + gc.collect() + except KeyboardInterrupt as e: + print("user stop: ", e) + except BaseException as e: + sys.print_exception(e) print(f"An error occurred during buffer used: {e}") finally: - if rgb888p_img is not None: - #先release掉申请的内存再stop - camera_release_image(CAM_DEV_ID_0,rgb888p_img) - camera_stop(CAM_DEV_ID_0) # 停止 camera display_deinit() # 释放 display det_kpu_deinit(kpu_licence_det) # 释放 车牌检测 kpu rec_kpu_deinit(kpu_licence_rec) # 释放 车牌识别 kpu gc.collect() - time.sleep(1) - ret = media_deinit() # 释放 整个media - if ret: - print("licence_det_rec, buffer_deinit failed") - return ret + media_deinit() # 释放 整个media print("licence_det_rec end") - return 0 if __name__ == '__main__': + os.exitpoint(os.EXITPOINT_ENABLE) licence_det_rec_inference() - - diff --git a/share/qtcreator/examples/04-AI-Demo/object_detect_yolov8n.py b/share/qtcreator/examples/04-AI-Demo/object_detect_yolov8n.py old mode 100755 new mode 100644 index 5ceb0a93bb3..d1f9428d355 --- a/share/qtcreator/examples/04-AI-Demo/object_detect_yolov8n.py +++ b/share/qtcreator/examples/04-AI-Demo/object_detect_yolov8n.py @@ -6,6 +6,7 @@ import image #图像模块,主要用于读取、图像绘制元素(框、点等)等操作 import time #时间统计 import gc #垃圾回收模块 +import os, sys #操作系统接口模块 ##config.py #display分辨率 @@ -338,7 +339,7 @@ def media_init(): config.comm_pool[0].blk_cnt = 1 config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE - ret = media.buffer_config(config) + media.buffer_config(config) global media_source, media_sink media_source = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) @@ -346,26 +347,24 @@ def media_init(): media.create_link(media_source, media_sink) # 初始化多媒体buffer - ret = media.buffer_init() - if ret: - return ret + media.buffer_init() global buffer, draw_img, osd_img buffer = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) # 图层1,用于画框 - draw_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, alloc=image.ALLOC_MPGC) + draw_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888) # 图层2,用于拷贝画框结果,防止画框过程中发生buffer搬运 osd_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, poolid=buffer.pool_id, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr) - return ret # media 释放内存 def media_deinit(): + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) global buffer,media_source, media_sink media.release_buffer(buffer) media.destroy_link(media_source, media_sink) - ret = media.buffer_deinit() - return ret + media.buffer_deinit() #**********for ob_detect.py********** @@ -375,51 +374,34 @@ def ob_detect_inference(): camera_init(CAM_DEV_ID_0) # 初始化 camera display_init() # 初始化 display - rgb888p_img = None try: - ret = media_init() - if ret: - print("ob_detect, buffer init failed") - return ret - + media_init() camera_start(CAM_DEV_ID_0) - time.sleep(5) while True: + os.exitpoint() with ScopedTiming("total",1): rgb888p_img = camera_read(CAM_DEV_ID_0) # 读取一帧图片 - if rgb888p_img == -1: - print("ob_detect, capture_image failed") - camera_release_image(CAM_DEV_ID_0,rgb888p_img) - rgb888p_img = None - continue - # for rgb888planar if rgb888p_img.format() == image.RGBP888: dets = kpu_run(kpu_ob_detect,rgb888p_img) # 执行多目标检测 kpu运行 以及 后处理过程 display_draw(dets) # 将得到的检测结果 绘制到 display camera_release_image(CAM_DEV_ID_0,rgb888p_img) # camera 释放图像 - rgb888p_img = None - # gc.collect() - except Exception as e: + gc.collect() + except KeyboardInterrupt as e: + print("user stop: ", e) + except BaseException as e: + sys.print_exception(e) print(f"An error occurred during buffer used: {e}") finally: - if rgb888p_img is not None: - #先release掉申请的内存再stop - camera_release_image(CAM_DEV_ID_0,rgb888p_img) - camera_stop(CAM_DEV_ID_0) # 停止camera display_deinit() # 释放 display kpu_deinit(kpu_ob_detect) # 释放 kpu gc.collect() - time.sleep(1) - ret = media_deinit() # 释放 整个media - if ret: - print("ob_detect, buffer_deinit failed") - return ret + media_deinit() # 释放 整个media print("ob_detect_test end") - return 0 if __name__ == '__main__': + os.exitpoint(os.EXITPOINT_ENABLE) ob_detect_inference() diff --git a/share/qtcreator/examples/04-AI-Demo/ocr_det.py b/share/qtcreator/examples/04-AI-Demo/ocr_det.py old mode 100755 new mode 100644 index e1e0fd3a630..a7f18e96c76 --- a/share/qtcreator/examples/04-AI-Demo/ocr_det.py +++ b/share/qtcreator/examples/04-AI-Demo/ocr_det.py @@ -6,7 +6,7 @@ import image #图像模块,主要用于读取、图像绘制元素(框、点等)等操作 import time #时间统计 import gc #垃圾回收模块 -import os #操作系统接口模块 +import os, sys #操作系统接口模块 import aicube #aicube模块,封装检测分割等任务相关后处理 # display分辨率 @@ -267,7 +267,7 @@ def media_init(): config.comm_pool[0].blk_cnt = 1 config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE - ret = media.buffer_config(config) + media.buffer_config(config) global media_source, media_sink media_source = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) @@ -275,26 +275,24 @@ def media_init(): media.create_link(media_source, media_sink) # 初始化多媒体buffer - ret = media.buffer_init() - if ret: - return ret + media.buffer_init() global buffer, draw_img, osd_img buffer = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) # 图层1,用于画框 - draw_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, alloc=image.ALLOC_MPGC) + draw_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888) # 图层2,用于拷贝画框结果,防止画框过程中发生buffer搬运 osd_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, poolid=buffer.pool_id, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr) - return ret # media 释放buffer,销毁link def media_deinit(): + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) global buffer,media_source, media_sink media.release_buffer(buffer) media.destroy_link(media_source, media_sink) - ret = media.buffer_deinit() - return ret + media.buffer_deinit() # def ocr_det_inference(): @@ -302,50 +300,33 @@ def ocr_det_inference(): kpu_ocr_det = kpu_init_det(kmodel_file_det) # 创建ocr检测任务的kpu对象 camera_init(CAM_DEV_ID_0) # 初始化 camera display_init() # 初始化 display - rgb888p_img = None try: - ret = media_init() - if ret: - print("ocr_det_test, buffer init failed") - return ret - + media_init() camera_start(CAM_DEV_ID_0) - time.sleep(5) while True: + os.exitpoint() with ScopedTiming("total",1): rgb888p_img = camera_read(CAM_DEV_ID_0) # 读取一帧图像 - if rgb888p_img == -1: - print("ocr_det_test, capture_image failed") - camera_release_image(CAM_DEV_ID_0,rgb888p_img) - rgb888p_img = None - continue - # for rgb888planar if rgb888p_img.format() == image.RGBP888: det_results = kpu_run_det(kpu_ocr_det,rgb888p_img) # kpu运行获取kmodel的推理输出 display_draw(det_results) # 绘制检测结果,并显示 camera_release_image(CAM_DEV_ID_0,rgb888p_img) # 释放内存 - rgb888p_img = None - # gc.collect() - except Exception as e: + gc.collect() + except KeyboardInterrupt as e: + print("user stop: ", e) + except BaseException as e: + sys.print_exception(e) print(f"An error occurred during buffer used: {e}") finally: - if rgb888p_img is not None: - #先release掉申请的内存再stop - camera_release_image(CAM_DEV_ID_0,rgb888p_img) - camera_stop(CAM_DEV_ID_0) # 停止camera display_deinit() # 释放display kpu_deinit_det(kpu_ocr_det) # 释放kpu gc.collect() - time.sleep(1) - ret = media_deinit() # 释放整个media - if ret: - print("ocr_det_test, buffer_deinit failed") - return ret + media_deinit() # 释放整个media print("ocr_det_test end") - return 0 if __name__ == '__main__': + os.exitpoint(os.EXITPOINT_ENABLE) ocr_det_inference() diff --git a/share/qtcreator/examples/04-AI-Demo/ocr_rec.py b/share/qtcreator/examples/04-AI-Demo/ocr_rec.py old mode 100755 new mode 100644 index a5d742a0e42..71805adb24c --- a/share/qtcreator/examples/04-AI-Demo/ocr_rec.py +++ b/share/qtcreator/examples/04-AI-Demo/ocr_rec.py @@ -7,6 +7,7 @@ import time #时间统计 import gc #垃圾回收模块 import aicube #aicube模块,封装检测分割等任务相关后处理 +import os, sys #操作系统接口模块 # display分辨率 DISPLAY_WIDTH = ALIGN_UP(1920, 16) @@ -351,7 +352,7 @@ def media_init(): config.comm_pool[0].blk_cnt = 1 config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE - ret = media.buffer_config(config) + media.buffer_config(config) global media_source, media_sink media_source = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) @@ -359,26 +360,24 @@ def media_init(): media.create_link(media_source, media_sink) # 初始化多媒体buffer - ret = media.buffer_init() - if ret: - return ret + media.buffer_init() global buffer, draw_img, osd_img buffer = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) # 图层1,用于画框 - draw_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, alloc=image.ALLOC_MPGC) + draw_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888) # 图层2,用于拷贝画框结果,防止画框过程中发生buffer搬运 osd_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, poolid=buffer.pool_id, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr) - return ret # media 释放buffer,销毁link def media_deinit(): + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) global buffer,media_source, media_sink media.release_buffer(buffer) media.destroy_link(media_source, media_sink) - ret = media.buffer_deinit() - return ret + media.buffer_deinit() def ocr_rec_inference(): print("ocr_rec_test start") @@ -386,23 +385,13 @@ def ocr_rec_inference(): kpu_ocr_rec = kpu_init_rec(kmodel_file_rec) # 创建OCR识别kpu对象 camera_init(CAM_DEV_ID_0) # camera初始化 display_init() # display初始化 - rgb888p_img = None try: - ret = media_init() - if ret: - print("ocr_rec_test, buffer init failed") - return ret - + media_init() camera_start(CAM_DEV_ID_0) - time.sleep(5) while True: + os.exitpoint() with ScopedTiming("total",1): rgb888p_img = camera_read(CAM_DEV_ID_0) # 读取一帧图像 - if rgb888p_img == -1: - print("ocr_rec_test, capture_image failed") - camera_release_image(CAM_DEV_ID_0,rgb888p_img) - rgb888p_img = None - continue # for rgb888planar if rgb888p_img.format() == image.RGBP888: det_results = kpu_run_det(kpu_ocr_det,rgb888p_img) # kpu运行获取OCR检测kmodel的推理输出 @@ -414,28 +403,22 @@ def ocr_rec_inference(): print("\n"+ocr_results) display_draw(det_results) camera_release_image(CAM_DEV_ID_0,rgb888p_img) - rgb888p_img = None - # gc.collect() - except Exception as e: + gc.collect() + except KeyboardInterrupt as e: + print("user stop: ", e) + except BaseException as e: + sys.print_exception(e) print(f"An error occurred during buffer used: {e}") finally: - if rgb888p_img is not None: - #先release掉申请的内存再stop - camera_release_image(CAM_DEV_ID_0,rgb888p_img) - camera_stop(CAM_DEV_ID_0) # 停止camera display_deinit() # 释放display kpu_deinit_det(kpu_ocr_det) # 释放OCR检测步骤kpu kpu_deinit_rec(kpu_ocr_rec) # 释放OCR识别步骤kpu gc.collect() - time.sleep(1) - ret = media_deinit() # 释放整个media - if ret: - print("ocr_rec_test, buffer_deinit failed") - return ret + media_deinit() # 释放整个media print("ocr_rec_test end") - return 0 if __name__ == '__main__': + os.exitpoint(os.EXITPOINT_ENABLE) ocr_rec_inference() diff --git a/share/qtcreator/examples/04-AI-Demo/person_detection.py b/share/qtcreator/examples/04-AI-Demo/person_detection.py old mode 100755 new mode 100644 index a99f643a8f6..58f47c65770 --- a/share/qtcreator/examples/04-AI-Demo/person_detection.py +++ b/share/qtcreator/examples/04-AI-Demo/person_detection.py @@ -8,7 +8,7 @@ import time #时间统计 import image #图像模块,主要用于读取、图像绘制元素(框、点等)等操作 - +import os, sys #操作系统接口模块 import gc #垃圾回收模块 ##config.py @@ -256,7 +256,7 @@ def media_init(): config.comm_pool[0].blk_cnt = 1 config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE - ret = media.buffer_config(config) + media.buffer_config(config) global media_source, media_sink media_source = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) @@ -264,26 +264,24 @@ def media_init(): media.create_link(media_source, media_sink) # 初始化多媒体buffer - ret = media.buffer_init() - if ret: - return ret + media.buffer_init() global buffer, draw_img, osd_img buffer = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) # 图层1,用于画框 - draw_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, alloc=image.ALLOC_MPGC) + draw_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888) # 图层2,用于拷贝画框结果,防止画框过程中发生buffer搬运 osd_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, poolid=buffer.pool_id, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr) - return ret # media 释放内存 def media_deinit(): + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) global buffer,media_source, media_sink media.release_buffer(buffer) media.destroy_link(media_source, media_sink) - ret = media.buffer_deinit() - return ret + media.buffer_deinit() #**********for person_detect.py********** def person_detect_inference(): @@ -292,50 +290,34 @@ def person_detect_inference(): camera_init(CAM_DEV_ID_0) # 初始化 camera display_init() # 初始化 display - rgb888p_img = None try: - ret = media_init() - if ret: - print("person_detect_test, buffer init failed") - return ret - + media_init() camera_start(CAM_DEV_ID_0) while True: + os.exitpoint() with ScopedTiming("total",total_debug_mode): rgb888p_img = camera_read(CAM_DEV_ID_0) # 读取一帧图片 - if rgb888p_img == -1: - print("person_detect_test, capture_image failed") - camera_release_image(CAM_DEV_ID_0,rgb888p_img) - rgb888p_img = None - continue - # for rgb888planar if rgb888p_img.format() == image.RGBP888: dets = kpu_run(kpu_person_detect,rgb888p_img) # 执行行人检测 kpu 运行 以及 后处理过程 display_draw(dets) # 将得到的检测结果 绘制到 display camera_release_image(CAM_DEV_ID_0,rgb888p_img) # camera 释放图像 - rgb888p_img = None - # gc.collect() - except Exception as e: + gc.collect() + except KeyboardInterrupt as e: + print("user stop: ", e) + except BaseException as e: + sys.print_exception(e) print(f"An error occurred during buffer used: {e}") finally: - if rgb888p_img is not None: - #先release掉申请的内存再stop - camera_release_image(CAM_DEV_ID_0,rgb888p_img) - camera_stop(CAM_DEV_ID_0) # 停止 camera display_deinit() # 释放 display kpu_deinit(kpu_person_detect) # 释放 kpu gc.collect() - ret = media_deinit() # 释放 整个media - if ret: - print("person_detect_test, buffer_deinit failed") - return ret + media_deinit() # 释放 整个media print("person_detect_test end") - return 0 if __name__ == '__main__': + os.exitpoint(os.EXITPOINT_ENABLE) person_detect_inference() - diff --git a/share/qtcreator/examples/04-AI-Demo/person_kp_detect.py b/share/qtcreator/examples/04-AI-Demo/person_kp_detect.py old mode 100755 new mode 100644 index f6d549d3d61..ec47c46cc75 --- a/share/qtcreator/examples/04-AI-Demo/person_kp_detect.py +++ b/share/qtcreator/examples/04-AI-Demo/person_kp_detect.py @@ -7,6 +7,7 @@ import time #时间统计 import gc #垃圾回收模块 import aidemo #aidemo模块,封装ai demo相关后处理、画图操作 +import os, sys #操作系统接口模块 ##config.py #display分辨率 @@ -271,7 +272,7 @@ def media_init(): config.comm_pool[0].blk_cnt = 1 config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE - ret = media.buffer_config(config) + media.buffer_config(config) global media_source, media_sink media_source = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) @@ -279,26 +280,24 @@ def media_init(): media.create_link(media_source, media_sink) # 初始化多媒体buffer - ret = media.buffer_init() - if ret: - return ret + media.buffer_init() global buffer, draw_img, osd_img buffer = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) # 图层1,用于画框 - draw_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, alloc=image.ALLOC_MPGC) + draw_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888) # 图层2,用于拷贝画框结果,防止画框过程中发生buffer搬运 osd_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, poolid=buffer.pool_id, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr) - return ret # media 释放内存 def media_deinit(): + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) global buffer,media_source, media_sink media.release_buffer(buffer) media.destroy_link(media_source, media_sink) - ret = media.buffer_deinit() - return ret + media.buffer_deinit() #**********for person_kp_detect.py********** @@ -308,51 +307,34 @@ def person_kp_detect_inference(): camera_init(CAM_DEV_ID_0) # 初始化 camera display_init() # 初始化 display - rgb888p_img = None try: - ret = media_init() - if ret: - print("person_kp_detect, buffer init failed") - return ret - + media_init() camera_start(CAM_DEV_ID_0) - time.sleep(5) while True: + os.exitpoint() with ScopedTiming("total",1): rgb888p_img = camera_read(CAM_DEV_ID_0) # 读取一帧图片 - if rgb888p_img == -1: - print("person_kp_detect, capture_image failed") - camera_release_image(CAM_DEV_ID_0,rgb888p_img) - rgb888p_img = None - continue - # for rgb888planar if rgb888p_img.format() == image.RGBP888: person_kp_detect_res = kpu_run(kpu_person_kp_detect,rgb888p_img) # 执行人体关键点检测 kpu 运行 以及 后处理过程 display_draw(person_kp_detect_res) # 将得到的人体关键点结果 绘制到 display camera_release_image(CAM_DEV_ID_0,rgb888p_img) # camera 释放图像 - rgb888p_img = None - #gc.collect() - except Exception as e: + gc.collect() + except KeyboardInterrupt as e: + print("user stop: ", e) + except BaseException as e: + sys.print_exception(e) print(f"An error occurred during buffer used: {e}") finally: - if rgb888p_img is not None: - #先release掉申请的内存再stop - camera_release_image(CAM_DEV_ID_0,rgb888p_img) - camera_stop(CAM_DEV_ID_0) # 停止 camera display_deinit() # 释放 display kpu_deinit(kpu_person_kp_detect) # 释放 kpu gc.collect() - time.sleep(1) - ret = media_deinit() # 释放 整个media - if ret: - print("person_kp_detect, buffer_deinit failed") - return ret + media_deinit() # 释放 整个media print("person_kp_detect end") - return 0 if __name__ == '__main__': + os.exitpoint(os.EXITPOINT_ENABLE) person_kp_detect_inference() diff --git a/share/qtcreator/examples/04-AI-Demo/segment_yolov8n.py b/share/qtcreator/examples/04-AI-Demo/segment_yolov8n.py old mode 100755 new mode 100644 index 6a6b9df5d54..d35f82f0391 --- a/share/qtcreator/examples/04-AI-Demo/segment_yolov8n.py +++ b/share/qtcreator/examples/04-AI-Demo/segment_yolov8n.py @@ -7,6 +7,7 @@ import time #时间统计 import gc #垃圾回收模块 import aidemo #aidemo模块,封装ai demo相关后处理、画图操作 +import os, sys #操作系统接口模块 ##config.py #display分辨率 @@ -252,7 +253,7 @@ def media_init(): config.comm_pool[0].blk_cnt = 1 config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE - ret = media.buffer_config(config) + media.buffer_config(config) global media_source, media_sink media_source = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) @@ -260,9 +261,7 @@ def media_init(): media.create_link(media_source, media_sink) # 初始化多媒体buffer - ret = media.buffer_init() - if ret: - return ret + media.buffer_init() global buffer, draw_img, osd_img, masks buffer = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) # 图层1,用于画框 @@ -271,16 +270,16 @@ def media_init(): # 图层2,用于拷贝画框结果,防止画框过程中发生buffer搬运 osd_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, poolid=buffer.pool_id, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr) - return ret # media 释放内存 def media_deinit(): + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) global buffer,media_source, media_sink media.release_buffer(buffer) media.destroy_link(media_source, media_sink) - ret = media.buffer_deinit() - return ret + media.buffer_deinit() #**********for seg.py********** @@ -290,51 +289,34 @@ def seg_inference(): camera_init(CAM_DEV_ID_0) # 初始化 camera display_init() # 初始化 display - rgb888p_img = None try: - ret = media_init() - if ret: - print("seg, buffer init failed") - return ret - + media_init() camera_start(CAM_DEV_ID_0) - time.sleep(5) while True: + os.exitpoint() with ScopedTiming("total",1): rgb888p_img = camera_read(CAM_DEV_ID_0) # 读取一帧图片 - if rgb888p_img == -1: - print("seg, capture_image failed") - camera_release_image(CAM_DEV_ID_0,rgb888p_img) - rgb888p_img = None - continue - # for rgb888planar if rgb888p_img.format() == image.RGBP888: seg_res = kpu_run(kpu_seg,rgb888p_img) # 执行多目标分割 kpu 运行 以及 后处理过程 display_draw(seg_res) # 将得到的分割结果 绘制到 display camera_release_image(CAM_DEV_ID_0,rgb888p_img) # camera 释放图像 - rgb888p_img = None - #gc.collect() - except Exception as e: + gc.collect() + except KeyboardInterrupt as e: + print("user stop: ", e) + except BaseException as e: + sys.print_exception(e) print(f"An error occurred during buffer used: {e}") finally: - if rgb888p_img is not None: - #先release掉申请的内存再stop - camera_release_image(CAM_DEV_ID_0,rgb888p_img) - camera_stop(CAM_DEV_ID_0) # 停止 camera display_deinit() # 释放 display kpu_deinit(kpu_seg) # 释放 kpu gc.collect() - time.sleep(1) - ret = media_deinit() # 释放 整个media - if ret: - print("seg, buffer_deinit failed") - return ret + media_deinit() # 释放 整个media print("seg end") - return 0 if __name__ == '__main__': + os.exitpoint(os.EXITPOINT_ENABLE) seg_inference() diff --git a/share/qtcreator/examples/05-nncase-Runtime/ai2d+kpu.py b/share/qtcreator/examples/05-nncase-Runtime/ai2d+kpu.py old mode 100755 new mode 100644 index 1e1c92a4a7d..daa80299df4 --- a/share/qtcreator/examples/05-nncase-Runtime/ai2d+kpu.py +++ b/share/qtcreator/examples/05-nncase-Runtime/ai2d+kpu.py @@ -1,11 +1,16 @@ -import nncase_runtime as nn -import ulab.numpy as np -import utime -import time -# init kpu and load kmodel +import nncase_runtime as nn # 导入nncase包 +import ulab.numpy as np # 导入numpy +import gc + +# We will explain how to use nncase_runtime in this test script for `KPU` and `AI2D`, +# including model reading, printing input and output information of the model, +# configuring `AI2D`, linking `AI2D` and `KPU`, setting input data, and how to obtain output. + + +# init kpu、ai2d and load kmodel kpu = nn.kpu() ai2d = nn.ai2d() -kpu.load_kmodel("/sdcard/app/tests/nncase_runtime/face_detection/face_detection.kmodel") +kpu.load_kmodel("/sdcard/app/tests/nncase_runtime/face_detection/face_detection_320.kmodel") # init kpu input data = np.zeros((1,3,320,320),dtype=np.uint8) @@ -26,7 +31,7 @@ ai2d_input = ai2d_input.reshape((1, 3, 624, 1024)) ai2d_input_tensor = nn.from_numpy(ai2d_input) - +# config ai2d ai2d.set_dtype(nn.ai2d_format.NCHW_FMT, nn.ai2d_format.NCHW_FMT, np.uint8, np.uint8) @@ -43,11 +48,16 @@ # get output for i in range(kpu.outputs_size()): - result = kpu.get_output_tensor(i) - result = result.to_numpy() - utime.sleep(1) - #file_ = "/sdcard/app/output_{}.bin".format(i) - #np.save(file_, result) + data = kpu.get_output_tensor(i) + result = data.to_numpy() print("result: ", i, result.flatten()[-5:]) print(result.shape,result.dtype) - + del data + +del kpu_input +del ai2d_input_tensor +del ai2d_builder +del ai2d_out +del ai2d +del kpu +gc.collect() diff --git a/share/qtcreator/examples/05-nncase-Runtime/kpu.py b/share/qtcreator/examples/05-nncase-Runtime/kpu.py old mode 100755 new mode 100644 index 399b20c737d..2b01dfe7655 --- a/share/qtcreator/examples/05-nncase-Runtime/kpu.py +++ b/share/qtcreator/examples/05-nncase-Runtime/kpu.py @@ -1,9 +1,14 @@ import nncase_runtime as nn import ulab.numpy as np +import gc + +# We will explain how to use nncase_runtime in this test script for `KPU`, +# including model reading, printing input and output information of the model, +# configuring input data, and how to obtain output. # init kpu and load kmodel kpu = nn.kpu() -kpu.load_kmodel("/sdcard/app/tests/mbv2/test.kmodel") +kpu.load_kmodel("/sdcard/app/tests/nncase_runtime/face_detection/face_detection_320.kmodel") # dump model input and output info print("inputs info:") @@ -15,19 +20,23 @@ print(kpu.outputs_desc(i)) # set input tensor -with open('/sdcard/app/tests/mbv2/input_0_0.bin', 'rb') as f: +with open('/sdcard/app/tests/nncase_runtime/face_detection/face_detection_ai2d_output.bin', 'rb') as f: data = f.read() -input_data = np.frombuffer(data, dtype=np.float) -input_data = input_data.reshape((1,3,224,224)) - +input_data = np.frombuffer(data, dtype=np.uint8) +input_data = input_data.reshape((1,3,320,320)) kpu.set_input_tensor(0, nn.from_numpy(input_data)) # run kmodel kpu.run() # get output -result = kpu.get_output_tensor(0) -result = result.to_numpy() -print(result.shape,result.dtype) - +for i in range(kpu.outputs_size()): + result = kpu.get_output_tensor(i) + data = result.to_numpy() + print("result: ", i, data.flatten()[-5:]) + print(data.shape, data.dtype) + del result + +del kpu +gc.collect() diff --git a/share/qtcreator/examples/07-April-Tags/find_apriltags.py b/share/qtcreator/examples/07-April-Tags/find_apriltags.py new file mode 100644 index 00000000000..633b73b2198 --- /dev/null +++ b/share/qtcreator/examples/07-April-Tags/find_apriltags.py @@ -0,0 +1,148 @@ +# AprilTags Example +# +# This example shows the power of the CanMV Cam to detect April Tags. + +from media.camera import * +from media.display import * +from media.media import * +import time, math, os, gc, sys + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 +SCALE = 4 +DETECT_WIDTH = DISPLAY_WIDTH // SCALE +DETECT_HEIGHT = DISPLAY_HEIGHT // SCALE + +# Note! Unlike find_qrcodes the find_apriltags method does not need lens correction on the image to work. + +# The apriltag code supports up to 6 tag families which can be processed at the same time. +# Returned tag objects will have their tag family and id within the tag family. + +tag_families = 0 +tag_families |= image.TAG16H5 # comment out to disable this family +tag_families |= image.TAG25H7 # comment out to disable this family +tag_families |= image.TAG25H9 # comment out to disable this family +tag_families |= image.TAG36H10 # comment out to disable this family +tag_families |= image.TAG36H11 # comment out to disable this family (default family) +tag_families |= image.ARTOOLKIT # comment out to disable this family + +# What's the difference between tag families? Well, for example, the TAG16H5 family is effectively +# a 4x4 square tag. So, this means it can be seen at a longer distance than a TAG36H11 tag which +# is a 6x6 square tag. However, the lower H value (H5 versus H11) means that the false positve +# rate for the 4x4 tag is much, much, much, higher than the 6x6 tag. So, unless you have a +# reason to use the other tags families just use TAG36H11 which is the default family. + +def family_name(tag): + if(tag.family() == image.TAG16H5): + return "TAG16H5" + if(tag.family() == image.TAG25H7): + return "TAG25H7" + if(tag.family() == image.TAG25H9): + return "TAG25H9" + if(tag.family() == image.TAG36H10): + return "TAG36H10" + if(tag.family() == image.TAG36H11): + return "TAG36H11" + if(tag.family() == image.ARTOOLKIT): + return "ARTOOLKIT" + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DETECT_WIDTH, DETECT_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def capture_picture(): + # create image for drawing + draw_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888) + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + yuv420_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = image.Image(yuv420_img.width(), yuv420_img.height(), image.GRAYSCALE, alloc=image.ALLOC_HEAP, data=yuv420_img) + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, yuv420_img) + draw_img.clear() + for tag in img.find_apriltags(families=tag_families): + draw_img.draw_rectangle([v*SCALE for v in tag.rect()], color=(255, 0, 0)) + draw_img.draw_cross(tag.cx()*SCALE, tag.cy()*SCALE, color=(0, 255, 0)) + print_args = (family_name(tag), tag.id(), (180 * tag.rotation()) / math.pi) + print("Tag Family %s, Tag ID %d, rotation %f (degrees)" % print_args) + draw_img.copy_to(osd_img) + print(fps.fps()) + del img + gc.collect() + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("camera capture") + capture_picture() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/07-April-Tags/find_apriltags_3d_pose.py b/share/qtcreator/examples/07-April-Tags/find_apriltags_3d_pose.py new file mode 100644 index 00000000000..c614fd9216d --- /dev/null +++ b/share/qtcreator/examples/07-April-Tags/find_apriltags_3d_pose.py @@ -0,0 +1,148 @@ +# AprilTags Example +# +# This example shows the power of the CanMV Cam to detect April Tags. + +from media.camera import * +from media.display import * +from media.media import * +import time, math, os, gc, sys + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 +SCALE = 4 +DETECT_WIDTH = DISPLAY_WIDTH // SCALE +DETECT_HEIGHT = DISPLAY_HEIGHT // SCALE + +# Note! Unlike find_qrcodes the find_apriltags method does not need lens correction on the image to work. + +# What's the difference between tag families? Well, for example, the TAG16H5 family is effectively +# a 4x4 square tag. So, this means it can be seen at a longer distance than a TAG36H11 tag which +# is a 6x6 square tag. However, the lower H value (H5 versus H11) means that the false positve +# rate for the 4x4 tag is much, much, much, higher than the 6x6 tag. So, unless you have a +# reason to use the other tags families just use TAG36H11 which is the default family. + +# The AprilTags library outputs the pose information for tags. This is the x/y/z translation and +# x/y/z rotation. The x/y/z rotation is in radians and can be converted to degrees. As for +# translation the units are dimensionless and you must apply a conversion function. + +# f_x is the x focal length of the camera. It should be equal to the lens focal length in mm +# divided by the x sensor size in mm times the number of pixels in the image. +# The below values are for the OV7725 camera with a 2.8 mm lens. + +# f_y is the y focal length of the camera. It should be equal to the lens focal length in mm +# divided by the y sensor size in mm times the number of pixels in the image. +# The below values are for the OV7725 camera with a 2.8 mm lens. + +# c_x is the image x center position in pixels. +# c_y is the image y center position in pixels. + +f_x = (2.8 / 3.984) * DETECT_WIDTH # find_apriltags defaults to this if not set +f_y = (2.8 / 2.952) * DETECT_HEIGHT # find_apriltags defaults to this if not set +c_x = DETECT_WIDTH * 0.5 # find_apriltags defaults to this if not set (the image.w * 0.5) +c_y = DETECT_HEIGHT * 0.5 # find_apriltags defaults to this if not set (the image.h * 0.5) + +def degrees(radians): + return (180 * radians) / math.pi + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DETECT_WIDTH, DETECT_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def capture_picture(): + # create image for drawing + draw_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888) + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + yuv420_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = image.Image(yuv420_img.width(), yuv420_img.height(), image.GRAYSCALE, alloc=image.ALLOC_HEAP, data=yuv420_img) + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, yuv420_img) + draw_img.clear() + for tag in img.find_apriltags(fx=f_x, fy=f_y, cx=c_x, cy=c_y): # defaults to TAG36H11 + draw_img.draw_rectangle([v*SCALE for v in tag.rect()], color=(255, 0, 0)) + draw_img.draw_cross(tag.cx()*SCALE, tag.cy()*SCALE, color=(0, 255, 0)) + print_args = (tag.x_translation(), tag.y_translation(), tag.z_translation(), + degrees(tag.x_rotation()), degrees(tag.y_rotation()), degrees(tag.z_rotation())) + # Translation units are unknown. Rotation units are in degrees. + print("Tx: %f, Ty %f, Tz %f, Rx %f, Ry %f, Rz %f" % print_args) + draw_img.copy_to(osd_img) + print(fps.fps()) + del img + gc.collect() + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("camera capture") + capture_picture() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/08-Codes/find_barcodes.py b/share/qtcreator/examples/08-Codes/find_barcodes.py new file mode 100644 index 00000000000..68f70ecda14 --- /dev/null +++ b/share/qtcreator/examples/08-Codes/find_barcodes.py @@ -0,0 +1,150 @@ +# Barcode Example +# +# This example shows off how easy it is to detect bar codes. + +from media.camera import * +from media.display import * +from media.media import * +import time, math, os, gc, sys + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 +SCALE = 4 +DETECT_WIDTH = DISPLAY_WIDTH // SCALE +DETECT_HEIGHT = DISPLAY_HEIGHT // SCALE + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DETECT_WIDTH, DETECT_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def barcode_name(code): + if(code.type() == image.EAN2): + return "EAN2" + if(code.type() == image.EAN5): + return "EAN5" + if(code.type() == image.EAN8): + return "EAN8" + if(code.type() == image.UPCE): + return "UPCE" + if(code.type() == image.ISBN10): + return "ISBN10" + if(code.type() == image.UPCA): + return "UPCA" + if(code.type() == image.EAN13): + return "EAN13" + if(code.type() == image.ISBN13): + return "ISBN13" + if(code.type() == image.I25): + return "I25" + if(code.type() == image.DATABAR): + return "DATABAR" + if(code.type() == image.DATABAR_EXP): + return "DATABAR_EXP" + if(code.type() == image.CODABAR): + return "CODABAR" + if(code.type() == image.CODE39): + return "CODE39" + if(code.type() == image.PDF417): + return "PDF417" + if(code.type() == image.CODE93): + return "CODE93" + if(code.type() == image.CODE128): + return "CODE128" + +def capture_picture(): + # create image for drawing + draw_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888) + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + yuv420_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = image.Image(yuv420_img.width(), yuv420_img.height(), image.GRAYSCALE, alloc=image.ALLOC_HEAP, data=yuv420_img) + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, yuv420_img) + codes = img.find_qrcodes() + draw_img.clear() + for code in codes: + draw_img.draw_rectangle([v*SCALE for v in code.rect()], color=(255, 0, 0)) + print_args = (barcode_name(code), code.payload(), (180 * code.rotation()) / math.pi, code.quality(), fps.fps()) + print("Barcode %s, Payload \"%s\", rotation %f (degrees), quality %d, FPS %f" % print_args) + draw_img.copy_to(osd_img) + if not codes: + print("FPS %f" % fps.fps()) + del img + gc.collect() + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("camera capture") + capture_picture() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/08-Codes/find_datamatrices.py b/share/qtcreator/examples/08-Codes/find_datamatrices.py new file mode 100644 index 00000000000..271130574cf --- /dev/null +++ b/share/qtcreator/examples/08-Codes/find_datamatrices.py @@ -0,0 +1,116 @@ +# Data Matrices Example +# +# This example shows off how easy it is to detect data matrices. + +from media.camera import * +from media.display import * +from media.media import * +import time, math, os, gc, sys + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 +SCALE = 4 +DETECT_WIDTH = DISPLAY_WIDTH // SCALE +DETECT_HEIGHT = DISPLAY_HEIGHT // SCALE + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DETECT_WIDTH, DETECT_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def capture_picture(): + # create image for drawing + draw_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888) + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + yuv420_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = image.Image(yuv420_img.width(), yuv420_img.height(), image.GRAYSCALE, alloc=image.ALLOC_HEAP, data=yuv420_img) + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, yuv420_img) + matrices = img.find_datamatrices() + draw_img.clear() + for matrix in matrices: + draw_img.draw_rectangle([v*SCALE for v in matrix.rect()], color=(255, 0, 0)) + print_args = (matrix.rows(), matrix.columns(), matrix.payload(), (180 * matrix.rotation()) / math.pi, fps.fps()) + print("Matrix [%d:%d], Payload \"%s\", rotation %f (degrees), FPS %f" % print_args) + draw_img.copy_to(osd_img) + if not matrices: + print("FPS %f" % fps.fps()) + del img + gc.collect() + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("camera capture") + capture_picture() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/08-Codes/find_qrcodes.py b/share/qtcreator/examples/08-Codes/find_qrcodes.py new file mode 100644 index 00000000000..ec0bd57593e --- /dev/null +++ b/share/qtcreator/examples/08-Codes/find_qrcodes.py @@ -0,0 +1,115 @@ +# QRCode Example +# +# This example shows the power of the CanMV Cam to detect QR Codes. + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 +SCALE = 4 +DETECT_WIDTH = DISPLAY_WIDTH // SCALE +DETECT_HEIGHT = DISPLAY_HEIGHT // SCALE + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DETECT_WIDTH, DETECT_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def capture_picture(): + # create image for drawing + draw_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888) + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + yuv420_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = image.Image(yuv420_img.width(), yuv420_img.height(), image.GRAYSCALE, alloc=image.ALLOC_HEAP, data=yuv420_img) + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, yuv420_img) + codes = img.find_qrcodes() + draw_img.clear() + for code in codes: + draw_img.draw_rectangle([v*SCALE for v in code.rect()], color=(255, 0, 0)) + print(code) + draw_img.copy_to(osd_img) + if not codes: + print("FPS %f" % fps.fps()) + del img + gc.collect() + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("camera capture") + capture_picture() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/09-Color-Tracking/automatic_grayscale_color_tracking.py b/share/qtcreator/examples/09-Color-Tracking/automatic_grayscale_color_tracking.py new file mode 100644 index 00000000000..c97e1286ecf --- /dev/null +++ b/share/qtcreator/examples/09-Color-Tracking/automatic_grayscale_color_tracking.py @@ -0,0 +1,145 @@ +# Automatic Grayscale Color Tracking Example +# +# This example shows off single color automatic grayscale color tracking using the CanMV Cam. + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys, math + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 +SCALE = 4 +DETECT_WIDTH = DISPLAY_WIDTH // SCALE +DETECT_HEIGHT = DISPLAY_HEIGHT // SCALE + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DETECT_WIDTH, DETECT_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_RGB_888) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def capture_picture(): + # create image for drawing + draw_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888) + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + # Capture the color thresholds for whatever was in the center of the image. + r = [(DETECT_WIDTH//2)-(50//2), (DETECT_HEIGHT//2)-(50//2), 50, 50] # 50x50 center of QVGA. + threshold = [128, 128] # Middle grayscale values. + frame_count = 0 + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + rgb888_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = rgb888_img.to_grayscale() + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, rgb888_img) + draw_img.clear() + if frame_count < 60: + if frame_count == 0: + print("Letting auto algorithms run. Don't put anything in front of the camera!") + print("Auto algorithms done. Hold the object you want to track in front of the camera in the box.") + print("MAKE SURE THE COLOR OF THE OBJECT YOU WANT TO TRACK IS FULLY ENCLOSED BY THE BOX!") + draw_img.draw_rectangle([v*SCALE for v in r]) + frame_count = frame_count + 1 + elif frame_count < 120: + if frame_count == 60: + print("Learning thresholds...") + elif frame_count == 119: + print("Thresholds learned...") + print("Tracking colors...") + hist = img.get_histogram(roi=r) + lo = hist.get_percentile(0.01) # Get the CDF of the histogram at the 1% range (ADJUST AS NECESSARY)! + hi = hist.get_percentile(0.99) # Get the CDF of the histogram at the 99% range (ADJUST AS NECESSARY)! + # Average in percentile values. + threshold[0] = (threshold[0] + lo.value()) // 2 + threshold[1] = (threshold[1] + hi.value()) // 2 + for blob in img.find_blobs([threshold], pixels_threshold=100, area_threshold=100, merge=True, margin=10): + draw_img.draw_rectangle([v*SCALE for v in blob.rect()]) + draw_img.draw_cross(blob.cx()*SCALE, blob.cy()*SCALE) + draw_img.draw_rectangle([v*SCALE for v in r]) + frame_count = frame_count + 1 + del hist + else: + for blob in img.find_blobs([threshold], pixels_threshold=100, area_threshold=100, merge=True, margin=10): + draw_img.draw_rectangle([v*SCALE for v in blob.rect()]) + draw_img.draw_cross(blob.cx()*SCALE, blob.cy()*SCALE) + + draw_img.copy_to(osd_img) + del img + gc.collect() + if frame_count >= 120: + print(fps.fps()) + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("camera capture") + capture_picture() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/09-Color-Tracking/automatic_rgb565_color_tracking.py b/share/qtcreator/examples/09-Color-Tracking/automatic_rgb565_color_tracking.py new file mode 100644 index 00000000000..85efd03081e --- /dev/null +++ b/share/qtcreator/examples/09-Color-Tracking/automatic_rgb565_color_tracking.py @@ -0,0 +1,149 @@ +# Automatic RGB565 Color Tracking Example +# +# This example shows off single color automatic RGB565 color tracking using the CanMV Cam. + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys, math + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 +SCALE = 4 +DETECT_WIDTH = DISPLAY_WIDTH // SCALE +DETECT_HEIGHT = DISPLAY_HEIGHT // SCALE + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DETECT_WIDTH, DETECT_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_RGB_888) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def capture_picture(): + # create image for drawing + draw_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888) + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + # Capture the color thresholds for whatever was in the center of the image. + r = [(DETECT_WIDTH//2)-(50//2), (DETECT_HEIGHT//2)-(50//2), 50, 50] # 50x50 center of QVGA. + threshold = [50, 50, 0, 0, 0, 0] # Middle L, A, B values. + frame_count = 0 + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + rgb888_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = rgb888_img.to_rgb565() + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, rgb888_img) + draw_img.clear() + if frame_count < 60: + if frame_count == 0: + print("Letting auto algorithms run. Don't put anything in front of the camera!") + print("Auto algorithms done. Hold the object you want to track in front of the camera in the box.") + print("MAKE SURE THE COLOR OF THE OBJECT YOU WANT TO TRACK IS FULLY ENCLOSED BY THE BOX!") + draw_img.draw_rectangle([v*SCALE for v in r]) + frame_count = frame_count + 1 + elif frame_count < 120: + if frame_count == 60: + print("Learning thresholds...") + elif frame_count == 119: + print("Thresholds learned...") + print("Tracking colors...") + hist = img.get_histogram(roi=r) + lo = hist.get_percentile(0.01) # Get the CDF of the histogram at the 1% range (ADJUST AS NECESSARY)! + hi = hist.get_percentile(0.99) # Get the CDF of the histogram at the 99% range (ADJUST AS NECESSARY)! + # Average in percentile values. + threshold[0] = (threshold[0] + lo.l_value()) // 2 + threshold[1] = (threshold[1] + hi.l_value()) // 2 + threshold[2] = (threshold[2] + lo.a_value()) // 2 + threshold[3] = (threshold[3] + hi.a_value()) // 2 + threshold[4] = (threshold[4] + lo.b_value()) // 2 + threshold[5] = (threshold[5] + hi.b_value()) // 2 + for blob in img.find_blobs([threshold], pixels_threshold=100, area_threshold=100, merge=True, margin=10): + draw_img.draw_rectangle([v*SCALE for v in blob.rect()]) + draw_img.draw_cross(blob.cx()*SCALE, blob.cy()*SCALE) + draw_img.draw_rectangle([v*SCALE for v in r]) + frame_count = frame_count + 1 + del hist + else: + for blob in img.find_blobs([threshold], pixels_threshold=100, area_threshold=100, merge=True, margin=10): + draw_img.draw_rectangle([v*SCALE for v in blob.rect()]) + draw_img.draw_cross(blob.cx()*SCALE, blob.cy()*SCALE) + + draw_img.copy_to(osd_img) + del img + gc.collect() + if frame_count >= 120: + print(fps.fps()) + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("camera capture") + capture_picture() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/09-Color-Tracking/black_grayscale_line_following.py b/share/qtcreator/examples/09-Color-Tracking/black_grayscale_line_following.py new file mode 100644 index 00000000000..beded0344e9 --- /dev/null +++ b/share/qtcreator/examples/09-Color-Tracking/black_grayscale_line_following.py @@ -0,0 +1,171 @@ +# Black Grayscale Line Following Example +# +# Making a line following robot requires a lot of effort. This example script +# shows how to do the machine vision part of the line following robot. You +# can use the output from this script to drive a differential drive robot to +# follow a line. This script just generates a single turn value that tells +# your robot to go left or right. +# +# For this script to work properly you should point the camera at a line at a +# 45 or so degree angle. Please make sure that only the line is within the +# camera's field of view. + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys, math + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 +SCALE = 4 +DETECT_WIDTH = DISPLAY_WIDTH // SCALE +DETECT_HEIGHT = DISPLAY_HEIGHT // SCALE + +# Tracks a black line. Use [(128, 255)] for a tracking a white line. +GRAYSCALE_THRESHOLD = [(0, 64)] + +# Each roi is (x, y, w, h). The line detection algorithm will try to find the +# centroid of the largest blob in each roi. The x position of the centroids +# will then be averaged with different weights where the most weight is assigned +# to the roi near the bottom of the image and less to the next roi and so on. +ROIS = [ # [ROI, weight] + (0, 100, 160, 20, 0.7), # You'll need to tweak the weights for your app + (0, 50, 160, 20, 0.3), # depending on how your robot is setup. + (0, 0, 160, 20, 0.1) + ] + +# Compute the weight divisor (we're computing this so you don't have to make weights add to 1). +weight_sum = 0 +for r in ROIS: weight_sum += r[4] # r[4] is the roi weight. + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DETECT_WIDTH, DETECT_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_RGB_888) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def capture_picture(): + # create image for drawing + draw_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888) + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + rgb888_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = rgb888_img.to_grayscale() + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, rgb888_img) + draw_img.clear() + centroid_sum = 0 + for r in ROIS: + blobs = img.find_blobs(GRAYSCALE_THRESHOLD, roi=r[0:4], merge=True) # r[0:4] is roi tuple. + + if blobs: + # Find the blob with the most pixels. + largest_blob = max(blobs, key=lambda b: b.pixels()) + + # Draw a rect around the blob. + draw_img.draw_rectangle([v*SCALE for v in largest_blob.rect()]) + draw_img.draw_cross(largest_blob.cx()*SCALE, largest_blob.cy()*SCALE) + + centroid_sum += largest_blob.cx() * r[4] # r[4] is the roi weight. + + center_pos = (centroid_sum / weight_sum) # Determine center of line. + + # Convert the center_pos to a deflection angle. We're using a non-linear + # operation so that the response gets stronger the farther off the line we + # are. Non-linear operations are good to use on the output of algorithms + # like this to cause a response "trigger". + deflection_angle = 0 + + # The 80 is from half the X res, the 60 is from half the Y res. The + # equation below is just computing the angle of a triangle where the + # opposite side of the triangle is the deviation of the center position + # from the center and the adjacent side is half the Y res. This limits + # the angle output to around -45 to 45. (It's not quite -45 and 45). + deflection_angle = -math.atan((center_pos-80)/60) + + # Convert angle in radians to degrees. + deflection_angle = math.degrees(deflection_angle) + + # Now you have an angle telling you how much to turn the robot by which + # incorporates the part of the line nearest to the robot and parts of + # the line farther away from the robot for a better prediction. + print("Turn Angle: %f" % deflection_angle) + draw_img.copy_to(osd_img) + del img + gc.collect() + print(fps.fps()) + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("camera capture") + capture_picture() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/09-Color-Tracking/image_histogram_info.py b/share/qtcreator/examples/09-Color-Tracking/image_histogram_info.py new file mode 100644 index 00000000000..cea35e2e46f --- /dev/null +++ b/share/qtcreator/examples/09-Color-Tracking/image_histogram_info.py @@ -0,0 +1,106 @@ +# Image Histogram Info Example +# +# This script computes the histogram of the image and prints it out. + +# You can also pass get_histogram() an "roi=" to get just the histogram of that area. +# get_histogram() allows you to quickly determine the color channel information of +# any any area in the image. + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 +SCALE = 4 +DETECT_WIDTH = DISPLAY_WIDTH // SCALE +DETECT_HEIGHT = DISPLAY_HEIGHT // SCALE + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DETECT_WIDTH, DETECT_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_RGB_888) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def capture_picture(): + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + rgb888_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = rgb888_img.to_grayscale() + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, rgb888_img) + print(img.get_histogram(bins=8)) + del img + gc.collect() + print(fps.fps()) + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("camera capture") + capture_picture() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/09-Color-Tracking/image_statistics_info.py b/share/qtcreator/examples/09-Color-Tracking/image_statistics_info.py new file mode 100644 index 00000000000..ba5ab393cd1 --- /dev/null +++ b/share/qtcreator/examples/09-Color-Tracking/image_statistics_info.py @@ -0,0 +1,106 @@ +# Image Statistics Info Example +# +# This script computes the statistics of the image and prints it out. + +# You can also pass get_statistics() an "roi=" to get just the statistics of that area. +# get_statistics() allows you to quickly determine the color channel information of +# any any area in the image. + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 +SCALE = 4 +DETECT_WIDTH = DISPLAY_WIDTH // SCALE +DETECT_HEIGHT = DISPLAY_HEIGHT // SCALE + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DETECT_WIDTH, DETECT_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_RGB_888) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def capture_picture(): + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + rgb888_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = rgb888_img.to_grayscale() + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, rgb888_img) + print(img.get_statistics()) + del img + gc.collect() + print(fps.fps()) + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("camera capture") + capture_picture() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/09-Color-Tracking/multi_color_code_tracking.py b/share/qtcreator/examples/09-Color-Tracking/multi_color_code_tracking.py new file mode 100644 index 00000000000..954970307b8 --- /dev/null +++ b/share/qtcreator/examples/09-Color-Tracking/multi_color_code_tracking.py @@ -0,0 +1,141 @@ +# Multi Color Code Tracking Example +# +# This example shows off multi color code tracking using the CanMV Cam. +# +# A color code is a blob composed of two or more colors. The example below will +# only track colored objects which have two or more the colors below in them. + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys, math + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 +SCALE = 4 +DETECT_WIDTH = DISPLAY_WIDTH // SCALE +DETECT_HEIGHT = DISPLAY_HEIGHT // SCALE + +# Color Tracking Thresholds (L Min, L Max, A Min, A Max, B Min, B Max) +# The below thresholds track in general red/green things. You may wish to tune them... +thresholds = [(30, 100, 15, 127, 15, 127), # generic_red_thresholds -> index is 0 so code == (1 << 0) + (30, 100, -64, -8, -32, 32), # generic_green_thresholds -> index is 1 so code == (1 << 1) + (0, 15, 0, 40, -80, -20)] # generic_blue_thresholds -> index is 2 so code == (1 << 2) +# Codes are or'ed together when "merge=True" for "find_blobs". + +# Only blobs that with more pixels than "pixel_threshold" and more area than "area_threshold" are +# returned by "find_blobs" below. Change "pixels_threshold" and "area_threshold" if you change the +# camera resolution. "merge=True" must be set to merge overlapping color blobs for color codes. + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DETECT_WIDTH, DETECT_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_RGB_888) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def capture_picture(): + # create image for drawing + draw_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888) + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + rgb888_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = rgb888_img.to_rgb565() + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, rgb888_img) + draw_img.clear() + for blob in img.find_blobs(thresholds, pixels_threshold=100, area_threshold=100, merge=True): + if blob.code() == 3: # r/g code + draw_img.draw_rectangle([v*SCALE for v in blob.rect()]) + draw_img.draw_cross(blob.cx()*SCALE, blob.cy()*SCALE) + draw_img.draw_string(blob.x()*SCALE + 2, blob.y()*SCALE + 2, "r/g") + if blob.code() == 5: # r/b code + draw_img.draw_rectangle([v*SCALE for v in blob.rect()]) + draw_img.draw_cross(blob.cx()*SCALE, blob.cy()*SCALE) + draw_img.draw_string(blob.x()*SCALE + 2, blob.y()*SCALE + 2, "r/b") + if blob.code() == 6: # g/b code + draw_img.draw_rectangle([v*SCALE for v in blob.rect()]) + draw_img.draw_cross(blob.cx()*SCALE, blob.cy()*SCALE) + draw_img.draw_string(blob.x()*SCALE + 2, blob.y()*SCALE + 2, "g/b") + if blob.code() == 7: # r/g/b code + draw_img.draw_rectangle([v*SCALE for v in blob.rect()]) + draw_img.draw_cross(blob.cx()*SCALE, blob.cy()*SCALE) + draw_img.draw_string(blob.x()*SCALE + 2, blob.y()*SCALE + 2, "r/g/b") + draw_img.copy_to(osd_img) + del img + gc.collect() + print(fps.fps()) + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("camera capture") + capture_picture() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/09-Color-Tracking/single_color_code_tracking.py b/share/qtcreator/examples/09-Color-Tracking/single_color_code_tracking.py new file mode 100644 index 00000000000..10838ee7b7e --- /dev/null +++ b/share/qtcreator/examples/09-Color-Tracking/single_color_code_tracking.py @@ -0,0 +1,135 @@ +# Single Color Code Tracking Example +# +# This example shows off single color code tracking using the CanMV Cam. +# +# A color code is a blob composed of two or more colors. The example below will +# only track colored objects which have both the colors below in them. + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys, math + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 +SCALE = 4 +DETECT_WIDTH = DISPLAY_WIDTH // SCALE +DETECT_HEIGHT = DISPLAY_HEIGHT // SCALE + +# Color Tracking Thresholds (L Min, L Max, A Min, A Max, B Min, B Max) +# The below thresholds track in general red/green things. You may wish to tune them... +thresholds = [(30, 100, 15, 127, 15, 127), # generic_red_thresholds -> index is 0 so code == (1 << 0) + (30, 100, -64, -8, -32, 32)] # generic_green_thresholds -> index is 1 so code == (1 << 1) +# Codes are or'ed together when "merge=True" for "find_blobs" + +# Only blobs that with more pixels than "pixel_threshold" and more area than "area_threshold" are +# returned by "find_blobs" below. Change "pixels_threshold" and "area_threshold" if you change the +# camera resolution. "merge=True" must be set to merge overlapping color blobs for color codes. + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DETECT_WIDTH, DETECT_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_RGB_888) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def capture_picture(): + # create image for drawing + draw_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888) + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + rgb888_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = rgb888_img.to_rgb565() + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, rgb888_img) + draw_img.clear() + for blob in img.find_blobs(thresholds, pixels_threshold=100, area_threshold=100, merge=True): + if blob.code() == 3: # r/g code == (1 << 1) | (1 << 0) + # These values depend on the blob not being circular - otherwise they will be shaky. + # if blob.elongation() > 0.5: + # img.draw_edges(blob.min_corners(), color=(255,0,0)) + # img.draw_line(blob.major_axis_line(), color=(0,255,0)) + # img.draw_line(blob.minor_axis_line(), color=(0,0,255)) + # These values are stable all the time. + draw_img.draw_rectangle([v*SCALE for v in blob.rect()]) + draw_img.draw_cross(blob.cx()*SCALE, blob.cy()*SCALE) + # Note - the blob rotation is unique to 0-180 only. + draw_img.draw_keypoints([(blob.cx()*SCALE, blob.cy()*SCALE, int(math.degrees(blob.rotation())))], size=20) + draw_img.copy_to(osd_img) + del img + gc.collect() + print(fps.fps()) + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("camera capture") + capture_picture() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/10-Drawing/arrow_drawing.py b/share/qtcreator/examples/10-Drawing/arrow_drawing.py new file mode 100644 index 00000000000..bb63d445a52 --- /dev/null +++ b/share/qtcreator/examples/10-Drawing/arrow_drawing.py @@ -0,0 +1,105 @@ +# Arrow Drawing +# +# This example shows off drawing arrows on the CanMV Cam. + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys, urandom + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def draw(): + # create image for drawing + img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888) + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + fps = time.clock() + while True: + fps.tick() + img.clear() + for i in range(10): + x0 = (urandom.getrandbits(30) % (2*img.width())) - (img.width()//2) + y0 = (urandom.getrandbits(30) % (2*img.height())) - (img.height()//2) + x1 = (urandom.getrandbits(30) % (2*img.width())) - (img.width()//2) + y1 = (urandom.getrandbits(30) % (2*img.height())) - (img.height()//2) + r = (urandom.getrandbits(30) % 127) + 128 + g = (urandom.getrandbits(30) % 127) + 128 + b = (urandom.getrandbits(30) % 127) + 128 + # If the first argument is a scaler then this method expects + # to see x0, y0, x1, and y1. Otherwise, it expects a (x0,y0,x1,y1) tuple. + img.draw_arrow(x0, y0, x1, y1, color = (r, g, b), size = 30, thickness = 2) + img.copy_to(osd_img) + time.sleep(1) + os.exitpoint() + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("draw") + draw() + except KeyboardInterrupt as e: + print("user stop: ", e) + except BaseException as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/10-Drawing/circle_drawing.py b/share/qtcreator/examples/10-Drawing/circle_drawing.py new file mode 100644 index 00000000000..b495f786316 --- /dev/null +++ b/share/qtcreator/examples/10-Drawing/circle_drawing.py @@ -0,0 +1,104 @@ +# Circle Drawing +# +# This example shows off drawing circles on the CanMV Cam. + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys, urandom + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def draw(): + # create image for drawing + img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888) + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + fps = time.clock() + while True: + fps.tick() + img.clear() + for i in range(10): + x = (urandom.getrandbits(30) % (2*img.width())) - (img.width()//2) + y = (urandom.getrandbits(30) % (2*img.height())) - (img.height()//2) + radius = urandom.getrandbits(30) % (max(img.height(), img.width())//2) + r = (urandom.getrandbits(30) % 127) + 128 + g = (urandom.getrandbits(30) % 127) + 128 + b = (urandom.getrandbits(30) % 127) + 128 + # If the first argument is a scaler then this method expects + # to see x, y, and radius. Otherwise, it expects a (x,y,radius) tuple. + img.draw_circle(x, y, radius, color = (r, g, b), thickness = 2, fill = False) + img.copy_to(osd_img) + time.sleep(1) + os.exitpoint() + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("draw") + draw() + except KeyboardInterrupt as e: + print("user stop: ", e) + except BaseException as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/10-Drawing/cross_drawing.py b/share/qtcreator/examples/10-Drawing/cross_drawing.py new file mode 100644 index 00000000000..7ed92f877cb --- /dev/null +++ b/share/qtcreator/examples/10-Drawing/cross_drawing.py @@ -0,0 +1,103 @@ +# Cross Drawing +# +# This example shows off drawing crosses on the CanMV Cam. + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys, urandom + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def draw(): + # create image for drawing + img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888) + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + fps = time.clock() + while True: + fps.tick() + img.clear() + for i in range(10): + x = (urandom.getrandbits(30) % (2*img.width())) - (img.width()//2) + y = (urandom.getrandbits(30) % (2*img.height())) - (img.height()//2) + r = (urandom.getrandbits(30) % 127) + 128 + g = (urandom.getrandbits(30) % 127) + 128 + b = (urandom.getrandbits(30) % 127) + 128 + # If the first argument is a scaler then this method expects + # to see x and y. Otherwise, it expects a (x,y) tuple. + img.draw_cross(x, y, color = (r, g, b), size = 10, thickness = 2) + img.copy_to(osd_img) + time.sleep(1) + os.exitpoint() + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("draw") + draw() + except KeyboardInterrupt as e: + print("user stop: ", e) + except BaseException as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/10-Drawing/ellipse_drawing.py b/share/qtcreator/examples/10-Drawing/ellipse_drawing.py new file mode 100644 index 00000000000..767e3a7b7bf --- /dev/null +++ b/share/qtcreator/examples/10-Drawing/ellipse_drawing.py @@ -0,0 +1,107 @@ +# Ellipse Drawing +# +# This example shows off drawing ellipses on the CanMV Cam. + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys, urandom + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def draw(): + # create image for drawing + img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888) + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + fps = time.clock() + while True: + fps.tick() + img.clear() + for i in range(10): + x = (urandom.getrandbits(30) % (2*img.width())) - (img.width()//2) + y = (urandom.getrandbits(30) % (2*img.height())) - (img.height()//2) + radius_x = urandom.getrandbits(30) % (max(img.height(), img.width())//2) + radius_y = urandom.getrandbits(30) % (max(img.height(), img.width())//2) + rot = urandom.getrandbits(30) + r = (urandom.getrandbits(30) % 127) + 128 + g = (urandom.getrandbits(30) % 127) + 128 + b = (urandom.getrandbits(30) % 127) + 128 + # If the first argument is a scaler then this method expects + # to see x, y, radius x, and radius y. + # Otherwise, it expects a (x,y,radius_x,radius_y) tuple. + img.draw_ellipse(x, y, radius_x, radius_y, rot, color = (r, g, b), thickness = 2, fill = False) + img.copy_to(osd_img) + time.sleep(1) + os.exitpoint() + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("draw") + draw() + except KeyboardInterrupt as e: + print("user stop: ", e) + except BaseException as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/10-Drawing/flood_fill.py b/share/qtcreator/examples/10-Drawing/flood_fill.py new file mode 100644 index 00000000000..f452341ebbd --- /dev/null +++ b/share/qtcreator/examples/10-Drawing/flood_fill.py @@ -0,0 +1,103 @@ +# Flood Fill +# +# This example shows off flood filling areas in the image. + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # # set chn0 output size + # camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # # set chn0 output format + # camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # # create meida source device + # globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # # create meida sink device + # globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # # create meida link + # media.create_link(meida_source, meida_sink) + # # set display plane with video channel + # display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DISPLAY_WIDTH, DISPLAY_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_RGB_888) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + # media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def draw(): + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.RGB565, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + fps = time.clock() + while True: + fps.tick() + os.exitpoint() + rgb888_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = rgb888_img.to_rgb565() + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, rgb888_img) + x = img.width() // 2 + y = img.height() // 2 + img.flood_fill(x, y, seed_threshold=0.05, floating_thresholds=0.05, + color=(255, 0, 0), invert=False, clear_background=False) + img.copy_to(osd_img) + del img + gc.collect() + print(fps.fps()) + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("draw") + draw() + except KeyboardInterrupt as e: + print("user stop: ", e) + except BaseException as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/10-Drawing/image_drawing.py b/share/qtcreator/examples/10-Drawing/image_drawing.py new file mode 100644 index 00000000000..bd114b08be3 --- /dev/null +++ b/share/qtcreator/examples/10-Drawing/image_drawing.py @@ -0,0 +1,110 @@ +# Draw Image Example +# +# This example shows off how to draw images in the frame buffer. + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # # set chn0 output size + # camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # # set chn0 output format + # camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # # create meida source device + # globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # # create meida sink device + # globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # # create meida link + # media.create_link(meida_source, meida_sink) + # # set display plane with video channel + # display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DISPLAY_WIDTH, DISPLAY_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_RGB_888) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + # media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def draw(): + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.RGB565, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + rgb888_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = rgb888_img.to_rgb565() + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, rgb888_img) + small_img = img.mean_pooled(4, 4) # Makes a copy. + x = (img.width()//2)-(small_img.width()//2) + y = (img.height()//2)-(small_img.height()//2) + # Draws an image in the frame buffer.Pass an optional + # mask image to control what pixels are drawn. + img.draw_image(small_img, x, y, x_scale=1, y_scale=1) + img.copy_to(osd_img) + del img, small_img + gc.collect() + print(fps.fps()) + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("draw") + draw() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/10-Drawing/image_drawing_advanced.py b/share/qtcreator/examples/10-Drawing/image_drawing_advanced.py new file mode 100644 index 00000000000..775f9464042 --- /dev/null +++ b/share/qtcreator/examples/10-Drawing/image_drawing_advanced.py @@ -0,0 +1,183 @@ +# Draw Image Testing script with bounce +# +# Exercise draw image with many different values for testing + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 + +BOUNCE = True +RESCALE = True + +SMALL_IMAGE_SCALE = 3 + +CYCLE_FORMATS = True +CYCLE_MASK = True + +# Used when CYCLE_FORMATS or CYCLE_MASK is true +value_mixer_init = 0 + +# Location of small image +x_init = 100 +y_init = 50 + +# Bounce direction +xd_init = 1 +yd_init = 1 + +# Small image scaling +rescale_init = 1.0 +rd_init = 0.1 +max_rescale = 5 +min_rescale = 0.2 + +# Boundary to bounce within +xmin = -DISPLAY_WIDTH / SMALL_IMAGE_SCALE - 8 +ymin = -DISPLAY_HEIGHT / SMALL_IMAGE_SCALE - 8 +xmax = DISPLAY_WIDTH + 8 +ymax = DISPLAY_HEIGHT + 8 + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # # set chn0 output size + # camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # # set chn0 output format + # camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # # create meida source device + # globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # # create meida sink device + # globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # # create meida link + # media.create_link(meida_source, meida_sink) + # # set display plane with video channel + # display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DISPLAY_WIDTH, DISPLAY_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_RGB_888) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + # media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def draw(): + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.RGB565, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + value_mixer = value_mixer_init + x = x_init + y = y_init + xd = xd_init + yd = yd_init + rescale = rescale_init + rd = rd_init + fps = time.clock() + while True: + fps.tick() + status = "" + value_mixer = value_mixer + 1 + try: + os.exitpoint() + rgb888_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = rgb888_img.to_rgb565() + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, rgb888_img) + small_img = img.mean_pooled(SMALL_IMAGE_SCALE, SMALL_IMAGE_SCALE) + status = 'rgb565 ' + if CYCLE_FORMATS: + image_format = (value_mixer >> 8) & 3 + # To test combining different formats + if (image_format==1): small_img = small_img.to_bitmap(); status = 'bitmap ' + if (image_format==2): small_img = small_img.to_grayscale(); status = 'grayscale ' + if (image_format==3): small_img = small_img.to_rgb565(); status = 'rgb565 ' + + # update small image location + if BOUNCE: + x = x + xd + if (xxmax): + xd = -xd + + y = y + yd + if (yymax): + yd = -yd + + # Update small image scale + if RESCALE: + rescale = rescale + rd + if (rescalemax_rescale): + rd = -rd + + # Find the center of the image + scaled_width = int(small_img.width() * abs(rescale)) + scaled_height= int(small_img.height() * abs(rescale)) + + apply_mask = CYCLE_MASK and ((value_mixer >> 9) & 1) + if apply_mask: + img.draw_image(small_img, int(x), int(y), mask=small_img.to_bitmap(), x_scale=rescale, y_scale=rescale, alpha=240) + status += 'alpha:240 ' + status += '+mask ' + else: + img.draw_image(small_img, int(x), int(y), x_scale=rescale, y_scale=rescale, alpha=128) + status += 'alpha:128 ' + + img.draw_string(8, 0, status, mono_space = False) + img.copy_to(osd_img) + del img, small_img + gc.collect() + print(fps.fps()) + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("draw") + draw() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/10-Drawing/image_drawing_alpha_blending_test.py b/share/qtcreator/examples/10-Drawing/image_drawing_alpha_blending_test.py new file mode 100644 index 00000000000..c301d85b74c --- /dev/null +++ b/share/qtcreator/examples/10-Drawing/image_drawing_alpha_blending_test.py @@ -0,0 +1,155 @@ +# Image Drawing Alpha Blending Test +# +# This script tests the performance and quality of the draw_image() +# method which can perform nearest neighbor, bilinear, bicubic, and +# area scaling along with color channel extraction, alpha blending, +# color palette application, and alpha palette application. + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 + +small_img = image.Image(4,4,image.RGB565) +small_img.set_pixel(0, 0, (0, 0, 127)) +small_img.set_pixel(1, 0, (47, 255, 199)) +small_img.set_pixel(2, 0, (0, 188, 255)) +small_img.set_pixel(3, 0, (0, 0, 127)) +small_img.set_pixel(0, 1, (0, 176, 255)) +small_img.set_pixel(1, 1, (222, 0, 0 )) +small_img.set_pixel(2, 1, (50, 255, 195)) +small_img.set_pixel(3, 1, (86, 255, 160)) +small_img.set_pixel(0, 2, (255, 211, 0 )) +small_img.set_pixel(1, 2, (83, 255, 163)) +small_img.set_pixel(2, 2, (255, 211, 0)) +small_img.set_pixel(3, 2, (0, 80, 255)) +small_img.set_pixel(0, 3, (255, 118, 0 )) +small_img.set_pixel(1, 3, (127, 0, 0 )) +small_img.set_pixel(2, 3, (0, 144, 255)) +small_img.set_pixel(3, 3, (50, 255, 195)) + +big_img = image.Image(128,128,image.RGB565) +big_img.draw_image(small_img, 0, 0, x_scale=32, y_scale=32) + +alpha_div = 1 +alpha_value_init = 0 +alpha_step_init = 2 + +x_bounce_init = DISPLAY_WIDTH//2 +x_bounce_toggle_init = 1 + +y_bounce_init = DISPLAY_HEIGHT//2 +y_bounce_toggle_init = 1 + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # # set chn0 output size + # camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # # set chn0 output format + # camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # # create meida source device + # globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # # create meida sink device + # globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # # create meida link + # media.create_link(meida_source, meida_sink) + # # set display plane with video channel + # display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DISPLAY_WIDTH, DISPLAY_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_RGB_888) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + # media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def draw(): + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.RGB565, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + alpha_value = alpha_value_init + alpha_step = alpha_step_init + x_bounce = x_bounce_init + x_bounce_toggle = x_bounce_toggle_init + y_bounce = y_bounce_init + y_bounce_toggle = y_bounce_toggle_init + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + rgb888_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = rgb888_img.to_rgb565() + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, rgb888_img) + img.draw_image(big_img, x_bounce, y_bounce, rgb_channel=-1, alpha=alpha_value//alpha_div) + + x_bounce += x_bounce_toggle + if abs(x_bounce-(img.width()//2)) >= (img.width()//2): x_bounce_toggle = -x_bounce_toggle + + y_bounce += y_bounce_toggle + if abs(y_bounce-(img.height()//2)) >= (img.height()//2): y_bounce_toggle = -y_bounce_toggle + + alpha_value += alpha_step + if not alpha_value or alpha_value//alpha_div == 256: alpha_step = -alpha_step + + img.copy_to(osd_img) + del img + gc.collect() + print(fps.fps()) + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("draw") + draw() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/10-Drawing/keypoints_drawing.py b/share/qtcreator/examples/10-Drawing/keypoints_drawing.py new file mode 100644 index 00000000000..09baf624629 --- /dev/null +++ b/share/qtcreator/examples/10-Drawing/keypoints_drawing.py @@ -0,0 +1,104 @@ +# Keypoints Drawing +# +# This example shows off drawing keypoints on the CanMV Cam. Usually you call draw_keypoints() +# on a keypoints object but you can also call it on a list of 3-value tuples... + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys, urandom + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def draw(): + # create image for drawing + img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888) + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + fps = time.clock() + while True: + fps.tick() + img.clear() + for i in range(10): + x = (urandom.getrandbits(30) % (2*img.width())) - (img.width()//2) + y = (urandom.getrandbits(30) % (2*img.height())) - (img.height()//2) + rot = urandom.getrandbits(30) % 360 + r = (urandom.getrandbits(30) % 127) + 128 + g = (urandom.getrandbits(30) % 127) + 128 + b = (urandom.getrandbits(30) % 127) + 128 + # This method draws a keypoints object or a list of (x, y, rot) tuples... + img.draw_keypoints([(x, y, rot)], color = (r, g, b), size = 20, thickness = 2, fill = False) + img.copy_to(osd_img) + time.sleep(1) + os.exitpoint() + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("draw") + draw() + except KeyboardInterrupt as e: + print("user stop: ", e) + except BaseException as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/10-Drawing/line_drawing.py b/share/qtcreator/examples/10-Drawing/line_drawing.py new file mode 100644 index 00000000000..0612dcf227a --- /dev/null +++ b/share/qtcreator/examples/10-Drawing/line_drawing.py @@ -0,0 +1,105 @@ +# Line Drawing +# +# This example shows off drawing lines on the CanMV Cam. + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys, urandom + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def draw(): + # create image for drawing + img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888) + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + fps = time.clock() + while True: + fps.tick() + img.clear() + for i in range(10): + x0 = (urandom.getrandbits(30) % (2*img.width())) - (img.width()//2) + y0 = (urandom.getrandbits(30) % (2*img.height())) - (img.height()//2) + x1 = (urandom.getrandbits(30) % (2*img.width())) - (img.width()//2) + y1 = (urandom.getrandbits(30) % (2*img.height())) - (img.height()//2) + r = (urandom.getrandbits(30) % 127) + 128 + g = (urandom.getrandbits(30) % 127) + 128 + b = (urandom.getrandbits(30) % 127) + 128 + # If the first argument is a scaler then this method expects + # to see x0, y0, x1, and y1. Otherwise, it expects a (x0,y0,x1,y1) tuple. + img.draw_line(x0, y0, x1, y1, color = (r, g, b), thickness = 2) + img.copy_to(osd_img) + time.sleep(1) + os.exitpoint() + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("draw") + draw() + except KeyboardInterrupt as e: + print("user stop: ", e) + except BaseException as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/10-Drawing/rectangle_drawing.py b/share/qtcreator/examples/10-Drawing/rectangle_drawing.py new file mode 100644 index 00000000000..e9685114d2a --- /dev/null +++ b/share/qtcreator/examples/10-Drawing/rectangle_drawing.py @@ -0,0 +1,105 @@ +# Rectangle Drawing +# +# This example shows off drawing rectangles on the CanMV Cam. + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys, urandom + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def draw(): + # create image for drawing + img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888) + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + fps = time.clock() + while True: + fps.tick() + img.clear() + for i in range(10): + x = (urandom.getrandbits(30) % (2*img.width())) - (img.width()//2) + y = (urandom.getrandbits(30) % (2*img.height())) - (img.height()//2) + w = (urandom.getrandbits(30) % (img.width()//2)) + h = (urandom.getrandbits(30) % (img.height()//2)) + r = (urandom.getrandbits(30) % 127) + 128 + g = (urandom.getrandbits(30) % 127) + 128 + b = (urandom.getrandbits(30) % 127) + 128 + # If the first argument is a scaler then this method expects + # to see x, y, w, and h. Otherwise, it expects a (x,y,w,h) tuple. + img.draw_rectangle(x, y, w, h, color = (r, g, b), thickness = 2, fill = False) + img.copy_to(osd_img) + time.sleep(1) + os.exitpoint() + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("draw") + draw() + except KeyboardInterrupt as e: + print("user stop: ", e) + except BaseException as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/10-Drawing/text_drawing.py b/share/qtcreator/examples/10-Drawing/text_drawing.py new file mode 100644 index 00000000000..d09d37bf13b --- /dev/null +++ b/share/qtcreator/examples/10-Drawing/text_drawing.py @@ -0,0 +1,106 @@ +# Text Drawing +# +# This example shows off drawing text on the CanMV Cam. + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys, urandom + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def draw(): + # create image for drawing + img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888) + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + fps = time.clock() + while True: + fps.tick() + img.clear() + for i in range(10): + x = (urandom.getrandbits(30) % (2*img.width())) - (img.width()//2) + y = (urandom.getrandbits(30) % (2*img.height())) - (img.height()//2) + r = (urandom.getrandbits(30) % 127) + 128 + g = (urandom.getrandbits(30) % 127) + 128 + b = (urandom.getrandbits(30) % 127) + 128 + # If the first argument is a scaler then this method expects + # to see x, y, and text. Otherwise, it expects a (x,y,text) tuple. + # Character and string rotation can be done at 0, 90, 180, 270, and etc. degrees. + img.draw_string(x, y, "Hello World!", color = (r, g, b), scale = 2, mono_space = False, + char_rotation = 0, char_hmirror = False, char_vflip = False, + string_rotation = 0, string_hmirror = False, string_vflip = False) + img.copy_to(osd_img) + time.sleep(1) + os.exitpoint() + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("draw") + draw() + except KeyboardInterrupt as e: + print("user stop: ", e) + except BaseException as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/11-Feature-Detection/edges.py b/share/qtcreator/examples/11-Feature-Detection/edges.py new file mode 100644 index 00000000000..817ec3b22f5 --- /dev/null +++ b/share/qtcreator/examples/11-Feature-Detection/edges.py @@ -0,0 +1,111 @@ +# Edge detection with Canny: +# +# This example demonstrates the Canny edge detector. + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 +SCALE = 4 +DETECT_WIDTH = DISPLAY_WIDTH // SCALE +DETECT_HEIGHT = DISPLAY_HEIGHT // SCALE + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DETECT_WIDTH, DETECT_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def capture_picture(): + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DETECT_WIDTH, DETECT_HEIGHT, image.GRAYSCALE, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + yuv420_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = image.Image(yuv420_img.width(), yuv420_img.height(), image.GRAYSCALE, data=yuv420_img) + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, yuv420_img) + # Use Canny edge detector + img.find_edges(image.EDGE_CANNY, threshold=(50, 80)) + # Faster simpler edge detection + #img.find_edges(image.EDGE_SIMPLE, threshold=(100, 255)) + img.copy_to(osd_img) + del img + gc.collect() + print(fps.fps()) + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("camera capture") + capture_picture() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/11-Feature-Detection/find_circles.py b/share/qtcreator/examples/11-Feature-Detection/find_circles.py new file mode 100644 index 00000000000..fd4f06c8239 --- /dev/null +++ b/share/qtcreator/examples/11-Feature-Detection/find_circles.py @@ -0,0 +1,131 @@ +# Find Circles Example +# +# This example shows off how to find circles in the image using the Hough +# Transform. https://en.wikipedia.org/wiki/Circle_Hough_Transform +# +# Note that the find_circles() method will only find circles which are completely +# inside of the image. Circles which go outside of the image/roi are ignored... + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 +SCALE = 4 +DETECT_WIDTH = DISPLAY_WIDTH // SCALE +DETECT_HEIGHT = DISPLAY_HEIGHT // SCALE + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DETECT_WIDTH, DETECT_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_RGB_888) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def capture_picture(): + # create image for drawing + draw_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888) + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + rgb888_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = rgb888_img.to_rgb565() + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, rgb888_img) + draw_img.clear() + # Circle objects have four values: x, y, r (radius), and magnitude. The + # magnitude is the strength of the detection of the circle. Higher is + # better... + + # `threshold` controls how many circles are found. Increase its value + # to decrease the number of circles detected... + + # `x_margin`, `y_margin`, and `r_margin` control the merging of similar + # circles in the x, y, and r (radius) directions. + + # r_min, r_max, and r_step control what radiuses of circles are tested. + # Shrinking the number of tested circle radiuses yields a big performance boost. + + for c in img.find_circles(threshold = 2000, x_margin = 10, y_margin = 10, r_margin = 10, + r_min = 2, r_max = 100, r_step = 2): + draw_img.draw_circle(c.x()*SCALE, c.y()*SCALE, c.r()*SCALE, color = (255, 0, 0)) + print(c) + draw_img.copy_to(osd_img) + del img + gc.collect() + print(fps.fps()) + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("camera capture") + capture_picture() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/11-Feature-Detection/find_lines.py b/share/qtcreator/examples/11-Feature-Detection/find_lines.py new file mode 100644 index 00000000000..c02d401eb53 --- /dev/null +++ b/share/qtcreator/examples/11-Feature-Detection/find_lines.py @@ -0,0 +1,146 @@ +# Find Lines Example +# +# This example shows off how to find lines in the image. For each line object +# found in the image a line object is returned which includes the line's rotation. + +# Note: Line detection is done by using the Hough Transform: +# http://en.wikipedia.org/wiki/Hough_transform +# Please read about it above for more information on what `theta` and `rho` are. + +# find_lines() finds infinite length lines. Use find_line_segments() to find non-infinite lines. + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 +SCALE = 4 +DETECT_WIDTH = DISPLAY_WIDTH // SCALE +DETECT_HEIGHT = DISPLAY_HEIGHT // SCALE + +# All line objects have a `theta()` method to get their rotation angle in degrees. +# You can filter lines based on their rotation angle. + +min_degree = 0 +max_degree = 179 + +# All lines also have `x1()`, `y1()`, `x2()`, and `y2()` methods to get their end-points +# and a `line()` method to get all the above as one 4 value tuple for `draw_line()`. + +# About negative rho values: +# +# A [theta+0:-rho] tuple is the same as [theta+180:+rho]. + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DETECT_WIDTH, DETECT_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_RGB_888) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def capture_picture(): + # create image for drawing + draw_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888) + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + rgb888_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = rgb888_img.to_rgb565() + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, rgb888_img) + draw_img.clear() + # `threshold` controls how many lines in the image are found. Only lines with + # edge difference magnitude sums greater than `threshold` are detected... + + # More about `threshold` - each pixel in the image contributes a magnitude value + # to a line. The sum of all contributions is the magintude for that line. Then + # when lines are merged their magnitudes are added togheter. Note that `threshold` + # filters out lines with low magnitudes before merging. To see the magnitude of + # un-merged lines set `theta_margin` and `rho_margin` to 0... + + # `theta_margin` and `rho_margin` control merging similar lines. If two lines + # theta and rho value differences are less than the margins then they are merged. + + for l in img.find_lines(threshold = 1000, theta_margin = 25, rho_margin = 25): + if (min_degree <= l.theta()) and (l.theta() <= max_degree): + draw_img.draw_line([v*SCALE for v in l.line()], color = (255, 0, 0)) + print(l) + draw_img.copy_to(osd_img) + del img + gc.collect() + print(fps.fps()) + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("camera capture") + capture_picture() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/11-Feature-Detection/find_rects.py b/share/qtcreator/examples/11-Feature-Detection/find_rects.py new file mode 100644 index 00000000000..889f1af7c98 --- /dev/null +++ b/share/qtcreator/examples/11-Feature-Detection/find_rects.py @@ -0,0 +1,123 @@ +# Find Rects Example +# +# This example shows off how to find rectangles in the image using the quad threshold +# detection code from our April Tags code. The quad threshold detection algorithm +# detects rectangles in an extremely robust way and is much better than Hough +# Transform based methods. For example, it can still detect rectangles even when lens +# distortion causes those rectangles to look bent. Rounded rectangles are no problem! +# (But, given this the code will also detect small radius circles too)... + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 +SCALE = 4 +DETECT_WIDTH = DISPLAY_WIDTH // SCALE +DETECT_HEIGHT = DISPLAY_HEIGHT // SCALE + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DETECT_WIDTH, DETECT_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_RGB_888) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def capture_picture(): + # create image for drawing + draw_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888) + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + rgb888_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = rgb888_img.to_rgb565() + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, rgb888_img) + draw_img.clear() + # `threshold` below should be set to a high enough value to filter out noise + # rectangles detected in the image which have low edge magnitudes. Rectangles + # have larger edge magnitudes the larger and more contrasty they are... + + for r in img.find_rects(threshold = 10000): + draw_img.draw_rectangle([v*SCALE for v in r.rect()], color = (255, 0, 0)) + for p in r.corners(): draw_img.draw_circle(p[0]*SCALE, p[1]*SCALE, 5*SCALE, color = (0, 255, 0)) + print(r) + draw_img.copy_to(osd_img) + del img + gc.collect() + print(fps.fps()) + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("camera capture") + capture_picture() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/11-Feature-Detection/hog.py b/share/qtcreator/examples/11-Feature-Detection/hog.py new file mode 100644 index 00000000000..f32c070ede3 --- /dev/null +++ b/share/qtcreator/examples/11-Feature-Detection/hog.py @@ -0,0 +1,111 @@ +# Histogram of Oriented Gradients (HoG) Example +# +# This example demonstrates HoG visualization. +# +# Note: Due to JPEG artifacts, the HoG visualization looks blurry. To see the +# image without JPEG artifacts, uncomment the lines that save the image to uSD. + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 +SCALE = 4 +DETECT_WIDTH = DISPLAY_WIDTH // SCALE +DETECT_HEIGHT = DISPLAY_HEIGHT // SCALE + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DETECT_WIDTH, DETECT_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def capture_picture(): + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DETECT_WIDTH, DETECT_HEIGHT, image.GRAYSCALE, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + yuv420_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = image.Image(yuv420_img.width(), yuv420_img.height(), image.GRAYSCALE, data=yuv420_img) + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, yuv420_img) + img.find_hog() + img.copy_to(osd_img) + del img + gc.collect() + print(fps.fps()) + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("camera capture") + capture_picture() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/11-Feature-Detection/keypoints.py b/share/qtcreator/examples/11-Feature-Detection/keypoints.py new file mode 100644 index 00000000000..64c013ffb2f --- /dev/null +++ b/share/qtcreator/examples/11-Feature-Detection/keypoints.py @@ -0,0 +1,145 @@ +# Object tracking with keypoints example. +# Show the camera an object and then run the script. A set of keypoints will be extracted +# once and then tracked in the following frames. If you want a new set of keypoints re-run +# the script. NOTE: see the docs for arguments to tune find_keypoints and match_keypoints. + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 +SCALE = 4 +DETECT_WIDTH = DISPLAY_WIDTH // SCALE +DETECT_HEIGHT = DISPLAY_HEIGHT // SCALE + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DETECT_WIDTH, DETECT_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_RGB_888) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def camera_drop(frame): + for i in range(frame): + os.exitpoint() + img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, img) + +def capture_picture(): + # create image for drawing + draw_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888) + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + kpts1 = None + # NOTE: uncomment to load a keypoints descriptor from file + #kpts1 = image.load_descriptor("/desc.orb") + camera_drop(60) + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + rgb888_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = rgb888_img.to_grayscale() + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, rgb888_img) + draw_img.clear() + if kpts1 == None: + # NOTE: By default find_keypoints returns multi-scale keypoints extracted from an image pyramid. + kpts1 = img.find_keypoints(max_keypoints=150, threshold=10, scale_factor=1.2) + if kpts1: + if SCALE == 1: + draw_img.draw_keypoints(kpts1) + draw_img.copy_to(osd_img) + time.sleep(2) + fps.reset() + else: + # NOTE: When extracting keypoints to match the first descriptor, we use normalized=True to extract + # keypoints from the first scale only, which will match one of the scales in the first descriptor. + kpts2 = img.find_keypoints(max_keypoints=150, threshold=10, normalized=True) + if kpts2: + match = image.match_descriptor(kpts1, kpts2, threshold=85) + if (match.count()>10): + # If we have at least n "good matches" + # Draw bounding rectangle and cross. + draw_img.draw_rectangle([v*SCALE for v in match.rect()]) + draw_img.draw_cross(match.cx()*SCALE, match.cy()*SCALE, size=10) + + print(kpts2, "matched:%d dt:%d"%(match.count(), match.theta())) + # NOTE: uncomment if you want to draw the keypoints + #img.draw_keypoints(kpts2, size=KEYPOINTS_SIZE, matched=True) + draw_img.copy_to(osd_img) + del img + gc.collect() + print(fps.fps()) + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("camera capture") + capture_picture() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/11-Feature-Detection/lbp.py b/share/qtcreator/examples/11-Feature-Detection/lbp.py new file mode 100644 index 00000000000..6d7e95c26ca --- /dev/null +++ b/share/qtcreator/examples/11-Feature-Detection/lbp.py @@ -0,0 +1,144 @@ +# Local Binary Patterns (LBP) Example +# +# This example shows off how to use the local binary pattern feature descriptor +# on your CanMV Cam. LBP descriptors work like Freak feature descriptors. +# +# WARNING: LBP supports needs to be reworked! As of right now this feature needs +# a lot of work to be made into somethin useful. This script will reamin to show +# that the functionality exists, but, in its current state is inadequate. + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 +SCALE = 4 +DETECT_WIDTH = DISPLAY_WIDTH // SCALE +DETECT_HEIGHT = DISPLAY_HEIGHT // SCALE + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DETECT_WIDTH, DETECT_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def camera_drop(frame): + for i in range(frame): + os.exitpoint() + img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, img) + +def capture_picture(): + # create image for drawing + draw_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888) + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + osd_img.draw_string(0, 0, "Please wait...") + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + # Load Haar Cascade + # By default this will use all stages, lower satges is faster but less accurate. + face_cascade = image.HaarCascade("frontalface", stages=25) + print(face_cascade) + d0 = None + #d0 = image.load_descriptor("/desc.lbp") + # Skip a few frames to allow the sensor settle down + # Note: This takes more time when exec from the IDE. + camera_drop(90) + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + yuv420_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = image.Image(yuv420_img.width(), yuv420_img.height(), image.GRAYSCALE, data=yuv420_img) + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, yuv420_img) + draw_img.clear() + objects = img.find_features(face_cascade, threshold=0.5, scale_factor=1.25) + if objects: + face = objects[0] + d1 = img.find_lbp(face) + if (d0 == None): + d0 = d1 + else: + dist = image.match_descriptor(d0, d1) + draw_img.draw_string(0, 10, "Match %d%%"%(dist)) + print("Match %d%%"%(dist)) + + draw_img.draw_rectangle([v*SCALE for v in face]) + # Draw FPS + draw_img.draw_string(0, 0, "FPS:%.2f"%(fps.fps())) + draw_img.copy_to(osd_img) + del img + gc.collect() + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("camera capture") + capture_picture() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/11-Feature-Detection/linear_regression_fast.py b/share/qtcreator/examples/11-Feature-Detection/linear_regression_fast.py new file mode 100644 index 00000000000..8f8856a01d2 --- /dev/null +++ b/share/qtcreator/examples/11-Feature-Detection/linear_regression_fast.py @@ -0,0 +1,130 @@ +# Fast Linear Regression Example +# +# This example shows off how to use the get_regression() method on your CanMV Cam +# to get the linear regression of a ROI. Using this method you can easily build +# a robot which can track lines which all point in the same general direction +# but are not actually connected. Use find_blobs() on lines that are nicely +# connected for better filtering options and control. +# +# This is called the fast linear regression because we use the least-squares +# method to fit the line. However, this method is NOT GOOD FOR ANY images that +# have a lot (or really any) outlier points which corrupt the line fit... + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 +SCALE = 4 +DETECT_WIDTH = DISPLAY_WIDTH // SCALE +DETECT_HEIGHT = DISPLAY_HEIGHT // SCALE + +THRESHOLD = (0, 100) # Grayscale threshold for dark things... +BINARY_VISIBLE = True # Does binary first so you can see what the linear regression + # is being run on... might lower FPS though. + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DETECT_WIDTH, DETECT_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def capture_picture(): + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DETECT_WIDTH, DETECT_HEIGHT, image.GRAYSCALE, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + osd_img.draw_string(0, 0, "Please wait...") + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + yuv420_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = image.Image(yuv420_img.width(), yuv420_img.height(), image.GRAYSCALE, data=yuv420_img) + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, yuv420_img) + img = img.binary([THRESHOLD]) if BINARY_VISIBLE else img + # Returns a line object similar to line objects returned by find_lines() and + # find_line_segments(). You have x1(), y1(), x2(), y2(), length(), + # theta() (rotation in degrees), rho(), and magnitude(). + # + # magnitude() represents how well the linear regression worked. It goes from + # (0, INF] where 0 is returned for a circle. The more linear the + # scene is the higher the magnitude. + line = img.get_regression([(255,255) if BINARY_VISIBLE else THRESHOLD]) + if (line): img.draw_line(line.line(), color = 127) + print("FPS %f, mag = %s" % (fps.fps(), str(line.magnitude()) if (line) else "N/A")) + img.copy_to(osd_img) + del img + gc.collect() + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("camera capture") + capture_picture() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/11-Feature-Detection/linear_regression_robust.py b/share/qtcreator/examples/11-Feature-Detection/linear_regression_robust.py new file mode 100644 index 00000000000..7b97425edcc --- /dev/null +++ b/share/qtcreator/examples/11-Feature-Detection/linear_regression_robust.py @@ -0,0 +1,132 @@ +# Robust Linear Regression Example +# +# This example shows off how to use the get_regression() method on your CanMV Cam +# to get the linear regression of a ROI. Using this method you can easily build +# a robot which can track lines which all point in the same general direction +# but are not actually connected. Use find_blobs() on lines that are nicely +# connected for better filtering options and control. +# +# We're using the robust=True argument for get_regression() in this script which +# computes the linear regression using a much more robust algorithm... but potentially +# much slower. The robust algorithm runs in O(N^2) time on the image. So, YOU NEED +# TO LIMIT THE NUMBER OF PIXELS the robust algorithm works on or it can actually +# take seconds for the algorithm to give you a result... THRESHOLD VERY CAREFULLY! + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 +SCALE = 4 +DETECT_WIDTH = DISPLAY_WIDTH // SCALE +DETECT_HEIGHT = DISPLAY_HEIGHT // SCALE + +THRESHOLD = (0, 100) # Grayscale threshold for dark things... +BINARY_VISIBLE = True # Does binary first so you can see what the linear regression + # is being run on... might lower FPS though. + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DETECT_WIDTH, DETECT_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def capture_picture(): + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DETECT_WIDTH, DETECT_HEIGHT, image.GRAYSCALE, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + osd_img.draw_string(0, 0, "Please wait...") + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + yuv420_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = image.Image(yuv420_img.width(), yuv420_img.height(), image.GRAYSCALE, data=yuv420_img) + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, yuv420_img) + img = img.binary([THRESHOLD]) if BINARY_VISIBLE else img + # Returns a line object similar to line objects returned by find_lines() and + # find_line_segments(). You have x1(), y1(), x2(), y2(), length(), + # theta() (rotation in degrees), rho(), and magnitude(). + # + # magnitude() represents how well the linear regression worked. It goes from + # (0, INF] where 0 is returned for a circle. The more linear the + # scene is the higher the magnitude. + line = img.get_regression([(255,255) if BINARY_VISIBLE else THRESHOLD], robust = True) + if (line): img.draw_line(line.line(), color = 127) + print("FPS %f, mag = %s" % (fps.fps(), str(line.magnitude()) if (line) else "N/A")) + img.copy_to(osd_img) + del img + gc.collect() + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("camera capture") + capture_picture() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/11-Feature-Detection/template_matching.py b/share/qtcreator/examples/11-Feature-Detection/template_matching.py new file mode 100644 index 00000000000..23e09713410 --- /dev/null +++ b/share/qtcreator/examples/11-Feature-Detection/template_matching.py @@ -0,0 +1,134 @@ +# Template Matching Example - Normalized Cross Correlation (NCC) +# +# This example shows off how to use the NCC feature of your CanMV Cam to match +# image patches to parts of an image... expect for extremely controlled enviorments +# NCC is not all to useful. +# +# WARNING: NCC supports needs to be reworked! As of right now this feature needs +# a lot of work to be made into somethin useful. This script will reamin to show +# that the functionality exists, but, in its current state is inadequate. + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys +from image import SEARCH_EX, SEARCH_DS + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 +SCALE = 4 +DETECT_WIDTH = DISPLAY_WIDTH // SCALE +DETECT_HEIGHT = DISPLAY_HEIGHT // SCALE + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DETECT_WIDTH, DETECT_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def capture_picture(): + # create image for drawing + draw_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888) + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + osd_img.draw_string(0, 0, "Please wait...") + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + # Load template. + # Template should be a small (eg. 32x32 pixels) grayscale image. + # template = image.Image("/sd/template.bmp") + # template.to_grayscale() + template = image.Image(32, 32, image.GRAYSCALE) + template.draw_circle(16,16,16,color=(255,255,255),fill=True) + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + yuv420_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = image.Image(yuv420_img.width(), yuv420_img.height(), image.GRAYSCALE, data=yuv420_img) + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, yuv420_img) + draw_img.clear() + # find_template(template, threshold, [roi, step, search]) + # ROI: The region of interest tuple (x, y, w, h). + # Step: The loop step used (y+=step, x+=step) use a bigger step to make it faster. + # Search is either image.SEARCH_EX for exhaustive search or image.SEARCH_DS for diamond search + # + # Note1: ROI has to be smaller than the image and bigger than the template. + # Note2: In diamond search, step and ROI are both ignored. + r = img.find_template(template, 0.50, step=4, search=SEARCH_EX) #, roi=(10, 0, 60, 60)) + if r: + draw_img.draw_rectangle([v*SCALE for v in r],color=(255,0,0)) + draw_img.copy_to(osd_img) + del img + gc.collect() + print(fps.fps()) + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("camera capture") + capture_picture() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/12-Image-Filters/adaptive_histogram_equalization.py b/share/qtcreator/examples/12-Image-Filters/adaptive_histogram_equalization.py new file mode 100644 index 00000000000..0444835aa7d --- /dev/null +++ b/share/qtcreator/examples/12-Image-Filters/adaptive_histogram_equalization.py @@ -0,0 +1,118 @@ +# Adaptive Histogram Equalization +# +# This example shows off how to use adaptive histogram equalization to improve +# the contrast in the image. Adaptive histogram equalization splits the image +# into regions and then equalizes the histogram in those regions to improve +# the image contrast versus a global histogram equalization. Additionally, +# you may specify a clip limit to prevent the contrast from going wild. + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 +SCALE = 4 +DETECT_WIDTH = DISPLAY_WIDTH // SCALE +DETECT_HEIGHT = DISPLAY_HEIGHT // SCALE + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DETECT_WIDTH, DETECT_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_RGB_888) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def capture_picture(): + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DETECT_WIDTH, DETECT_HEIGHT, image.RGB565, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + rgb888_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = rgb888_img.to_rgb565() + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, rgb888_img) + # A clip_limit of < 0 gives you normal adaptive histogram equalization + # which may result in huge amounts of contrast noise... + + # A clip_limit of 1 does nothing. For best results go slightly higher + # than 1 like below. The higher you go the closer you get back to + # standard adaptive histogram equalization with huge contrast swings. + img.histeq(adaptive=True, clip_limit=3) + img.copy_to(osd_img) + del img + gc.collect() + print(fps.fps()) + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("camera capture") + capture_picture() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/12-Image-Filters/blur_filter.py b/share/qtcreator/examples/12-Image-Filters/blur_filter.py new file mode 100644 index 00000000000..1dadebc45a4 --- /dev/null +++ b/share/qtcreator/examples/12-Image-Filters/blur_filter.py @@ -0,0 +1,109 @@ +# Blur Filter Example +# +# This example shows off using the guassian filter to blur images. + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 +SCALE = 4 +DETECT_WIDTH = DISPLAY_WIDTH // SCALE +DETECT_HEIGHT = DISPLAY_HEIGHT // SCALE + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DETECT_WIDTH, DETECT_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_RGB_888) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def capture_picture(): + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DETECT_WIDTH, DETECT_HEIGHT, image.RGB565, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + rgb888_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = rgb888_img.to_rgb565() + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, rgb888_img) + # Run the kernel on every pixel of the image. + img.gaussian(1) + img.copy_to(osd_img) + del img + gc.collect() + print(fps.fps()) + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("camera capture") + capture_picture() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/12-Image-Filters/cartoon_filter.py b/share/qtcreator/examples/12-Image-Filters/cartoon_filter.py new file mode 100644 index 00000000000..e1c44c69d46 --- /dev/null +++ b/share/qtcreator/examples/12-Image-Filters/cartoon_filter.py @@ -0,0 +1,119 @@ +# Cartoon Filter +# +# This example shows off a simple cartoon filter on images. The cartoon +# filter works by joining similar pixel areas of an image and replacing +# the pixels in those areas with the area mean. + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 +SCALE = 4 +DETECT_WIDTH = DISPLAY_WIDTH // SCALE +DETECT_HEIGHT = DISPLAY_HEIGHT // SCALE + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DETECT_WIDTH, DETECT_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_RGB_888) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def capture_picture(): + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DETECT_WIDTH, DETECT_HEIGHT, image.RGB565, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + rgb888_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = rgb888_img.to_rgb565() + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, rgb888_img) + # seed_threshold controls the maximum area growth of a colored + # region. Making this larger will merge more pixels. + + # floating_threshold controls the maximum pixel-to-pixel difference + # when growing a region. Settings this very high will quickly combine + # all pixels in the image. You should keep this small. + + # cartoon() will grow regions while both thresholds are statisfied... + + img.cartoon(seed_threshold=0.05, floating_thresholds=0.05) + img.copy_to(osd_img) + del img + gc.collect() + print(fps.fps()) + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("camera capture") + capture_picture() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/12-Image-Filters/color_bilateral_filter.py b/share/qtcreator/examples/12-Image-Filters/color_bilateral_filter.py new file mode 100644 index 00000000000..62feb0048a4 --- /dev/null +++ b/share/qtcreator/examples/12-Image-Filters/color_bilateral_filter.py @@ -0,0 +1,121 @@ +# Color Bilteral Filter Example +# +# This example shows off using the bilateral filter on color images. + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 +SCALE = 4 +DETECT_WIDTH = DISPLAY_WIDTH // SCALE +DETECT_HEIGHT = DISPLAY_HEIGHT // SCALE + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DETECT_WIDTH, DETECT_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_RGB_888) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def capture_picture(): + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DETECT_WIDTH, DETECT_HEIGHT, image.RGB565, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + rgb888_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = rgb888_img.to_rgb565() + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, rgb888_img) + # color_sigma controls how close color wise pixels have to be to each other to be + # blured togheter. A smaller value means they have to be closer. + # A larger value is less strict. + + # space_sigma controls how close space wise pixels have to be to each other to be + # blured togheter. A smaller value means they have to be closer. + # A larger value is less strict. + + # Run the kernel on every pixel of the image. + img.bilateral(3, color_sigma=0.1, space_sigma=1) + + # Note that the bilateral filter can introduce image defects if you set + # color_sigma/space_sigma to aggresively. Increase the sigma values until + # the defects go away if you see them. + img.copy_to(osd_img) + del img + gc.collect() + print(fps.fps()) + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("camera capture") + capture_picture() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/12-Image-Filters/color_binary_filter.py b/share/qtcreator/examples/12-Image-Filters/color_binary_filter.py new file mode 100644 index 00000000000..16f25b29452 --- /dev/null +++ b/share/qtcreator/examples/12-Image-Filters/color_binary_filter.py @@ -0,0 +1,135 @@ +# Color Binary Filter Example +# +# This script shows off the binary image filter. You may pass binary any +# number of thresholds to segment the image by. + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 +SCALE = 4 +DETECT_WIDTH = DISPLAY_WIDTH // SCALE +DETECT_HEIGHT = DISPLAY_HEIGHT // SCALE + +# Use the Tools -> Machine Vision -> Threshold Edtor to pick better thresholds. +red_threshold = (0,100, 0,127, 0,127) # L A B +green_threshold = (0,100, -128,0, 0,127) # L A B +blue_threshold = (0,100, -128,127, -128,0) # L A B + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DETECT_WIDTH, DETECT_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_RGB_888) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def capture_picture(): + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DETECT_WIDTH, DETECT_HEIGHT, image.RGB565, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + frame_count = 0 + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + rgb888_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = rgb888_img.to_rgb565() + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, rgb888_img) + # Test red threshold + if frame_count < 100: + img.binary([red_threshold]) + # Test green threshold + elif frame_count < 200: + img.binary([green_threshold]) + # Test blue threshold + elif frame_count < 300: + img.binary([blue_threshold]) + # Test not red threshold + elif frame_count < 400: + img.binary([red_threshold], invert = 1) + # Test not green threshold + elif frame_count < 500: + img.binary([green_threshold], invert = 1) + # Test not blue threshold + elif frame_count < 600: + img.binary([blue_threshold], invert = 1) + else: + frame_count = 0 + frame_count = frame_count + 1 + img.copy_to(osd_img) + del img + gc.collect() + print(fps.fps()) + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("camera capture") + capture_picture() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/12-Image-Filters/color_light_removal.py b/share/qtcreator/examples/12-Image-Filters/color_light_removal.py new file mode 100644 index 00000000000..c6319e79438 --- /dev/null +++ b/share/qtcreator/examples/12-Image-Filters/color_light_removal.py @@ -0,0 +1,115 @@ +# Color Light Removal +# +# This example shows off how to remove bright lights from the image. +# You can do this using the binary() method with the "zero=" argument. +# +# Removing bright lights from the image allows you to now use +# histeq() on the image without outliers from oversaturated +# parts of the image breaking the algorithm... + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 +SCALE = 4 +DETECT_WIDTH = DISPLAY_WIDTH // SCALE +DETECT_HEIGHT = DISPLAY_HEIGHT // SCALE + +thresholds = (90, 100, -128, 127, -128, 127) + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DETECT_WIDTH, DETECT_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_RGB_888) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def capture_picture(): + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DETECT_WIDTH, DETECT_HEIGHT, image.RGB565, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + rgb888_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = rgb888_img.to_rgb565() + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, rgb888_img) + img.binary([thresholds], invert=False, zero=True) + img.copy_to(osd_img) + del img + gc.collect() + print(fps.fps()) + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("camera capture") + capture_picture() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/12-Image-Filters/edge_filter.py b/share/qtcreator/examples/12-Image-Filters/edge_filter.py new file mode 100644 index 00000000000..84355a86d60 --- /dev/null +++ b/share/qtcreator/examples/12-Image-Filters/edge_filter.py @@ -0,0 +1,109 @@ +# Edge Filter Example +# +# This example shows off using the laplacian filter to detect edges. + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 +SCALE = 4 +DETECT_WIDTH = DISPLAY_WIDTH // SCALE +DETECT_HEIGHT = DISPLAY_HEIGHT // SCALE + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DETECT_WIDTH, DETECT_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_RGB_888) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def capture_picture(): + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DETECT_WIDTH, DETECT_HEIGHT, image.RGB565, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + rgb888_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = rgb888_img.to_rgb565() + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, rgb888_img) + # Run the kernel on every pixel of the image. + img.laplacian(1,sharpen=True) + img.copy_to(osd_img) + del img + gc.collect() + print(fps.fps()) + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("camera capture") + capture_picture() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/12-Image-Filters/erode_and_dilate.py b/share/qtcreator/examples/12-Image-Filters/erode_and_dilate.py new file mode 100644 index 00000000000..b38e868ca37 --- /dev/null +++ b/share/qtcreator/examples/12-Image-Filters/erode_and_dilate.py @@ -0,0 +1,136 @@ +# Erode and Dilate Example +# +# This example shows off the erode and dilate functions which you can run on +# a binary image to remove noise. This example was originally a test but its +# useful for showing off how these functions work. + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 +SCALE = 4 +DETECT_WIDTH = DISPLAY_WIDTH // SCALE +DETECT_HEIGHT = DISPLAY_HEIGHT // SCALE + +grayscale_thres = (170, 255) +rgb565_thres = (70, 100, -128, 127, -128, 127) + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DETECT_WIDTH, DETECT_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_RGB_888) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def capture_picture(): + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DETECT_WIDTH, DETECT_HEIGHT, image.RGB565, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + frame_count = 0 + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + rgb888_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = rgb888_img.to_rgb565() + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, rgb888_img) + # Test red threshold + if frame_count < 100: + img.binary([rgb565_thres]) + img.erode(2) + # Test green threshold + elif frame_count < 200: + img.binary([rgb565_thres]) + img.dilate(2) + # Test blue threshold + elif frame_count < 300: + img = img.to_grayscale() + img.binary([grayscale_thres]) + img.erode(2) + img = img.to_rgb565() + # Test not red threshold + elif frame_count < 400: + img = img.to_grayscale() + img.binary([grayscale_thres]) + img.dilate(2) + img = img.to_rgb565() + else: + frame_count = 0 + frame_count = frame_count + 1 + img.copy_to(osd_img) + del img + gc.collect() + print(fps.fps()) + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("camera capture") + capture_picture() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/12-Image-Filters/gamma_correction.py b/share/qtcreator/examples/12-Image-Filters/gamma_correction.py new file mode 100644 index 00000000000..646abd687b3 --- /dev/null +++ b/share/qtcreator/examples/12-Image-Filters/gamma_correction.py @@ -0,0 +1,111 @@ +# Gamma Correction +# +# This example shows off gamma correction to make the image brighter. The gamma +# correction method can also fix contrast and brightness too. + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 +SCALE = 4 +DETECT_WIDTH = DISPLAY_WIDTH // SCALE +DETECT_HEIGHT = DISPLAY_HEIGHT // SCALE + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DETECT_WIDTH, DETECT_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_RGB_888) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def capture_picture(): + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DETECT_WIDTH, DETECT_HEIGHT, image.RGB565, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + rgb888_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = rgb888_img.to_rgb565() + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, rgb888_img) + # Gamma, contrast, and brightness correction are applied to each color channel. The + # values are scaled to the range per color channel per image type... + img.gamma_corr(gamma = 0.5, contrast = 1.0, brightness = 0.0) + img.copy_to(osd_img) + del img + gc.collect() + print(fps.fps()) + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("camera capture") + capture_picture() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/12-Image-Filters/grayscale_bilateral_filter.py b/share/qtcreator/examples/12-Image-Filters/grayscale_bilateral_filter.py new file mode 100644 index 00000000000..57a82ed8c66 --- /dev/null +++ b/share/qtcreator/examples/12-Image-Filters/grayscale_bilateral_filter.py @@ -0,0 +1,122 @@ +# Grayscale Bilteral Filter Example +# +# This example shows off using the bilateral filter on grayscale images. + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 +SCALE = 4 +DETECT_WIDTH = DISPLAY_WIDTH // SCALE +DETECT_HEIGHT = DISPLAY_HEIGHT // SCALE + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DETECT_WIDTH, DETECT_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_RGB_888) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def capture_picture(): + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DETECT_WIDTH, DETECT_HEIGHT, image.GRAYSCALE, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + rgb888_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = rgb888_img.to_grayscale() + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, rgb888_img) + # color_sigma controls how close color wise pixels have to be to each other to be + # blured togheter. A smaller value means they have to be closer. + # A larger value is less strict. + + # space_sigma controls how close space wise pixels have to be to each other to be + # blured togheter. A smaller value means they have to be closer. + # A larger value is less strict. + + # Run the kernel on every pixel of the image. + img.bilateral(3, color_sigma=0.1, space_sigma=1) + + # Note that the bilateral filter can introduce image defects if you set + # color_sigma/space_sigma to aggresively. Increase the sigma values until + # the defects go away if you see them. + + img.copy_to(osd_img) + del img + gc.collect() + print(fps.fps()) + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("camera capture") + capture_picture() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/12-Image-Filters/grayscale_binary_filter.py b/share/qtcreator/examples/12-Image-Filters/grayscale_binary_filter.py new file mode 100644 index 00000000000..08d8e02211e --- /dev/null +++ b/share/qtcreator/examples/12-Image-Filters/grayscale_binary_filter.py @@ -0,0 +1,127 @@ +# Grayscale Binary Filter Example +# +# This script shows off the binary image filter. You may pass binary any +# number of thresholds to segment the image by. + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 +SCALE = 4 +DETECT_WIDTH = DISPLAY_WIDTH // SCALE +DETECT_HEIGHT = DISPLAY_HEIGHT // SCALE + +low_threshold = (0, 50) +high_threshold = (205, 255) + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DETECT_WIDTH, DETECT_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_RGB_888) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def capture_picture(): + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DETECT_WIDTH, DETECT_HEIGHT, image.GRAYSCALE, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + frame_count = 0 + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + rgb888_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = rgb888_img.to_grayscale() + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, rgb888_img) + # Test low threshold + if frame_count < 100: + img.binary([low_threshold]) + # Test high threshold + elif frame_count < 200: + img.binary([high_threshold]) + # Test not low threshold + elif frame_count < 300: + img.binary([low_threshold], invert = 1) + # Test not high threshold + elif frame_count < 400: + img.binary([high_threshold], invert = 1) + else: + frame_count = 0 + frame_count = frame_count + 1 + img.copy_to(osd_img) + del img + gc.collect() + print(fps.fps()) + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("camera capture") + capture_picture() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/12-Image-Filters/grayscale_light_removal.py b/share/qtcreator/examples/12-Image-Filters/grayscale_light_removal.py new file mode 100644 index 00000000000..b03181aed39 --- /dev/null +++ b/share/qtcreator/examples/12-Image-Filters/grayscale_light_removal.py @@ -0,0 +1,115 @@ +# Grayscale Light Removal +# +# This example shows off how to remove bright lights from the image. +# You can do this using the binary() method with the "zero=" argument. +# +# Removing bright lights from the image allows you to now use +# histeq() on the image without outliers from oversaturated +# parts of the image breaking the algorithm... + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 +SCALE = 4 +DETECT_WIDTH = DISPLAY_WIDTH // SCALE +DETECT_HEIGHT = DISPLAY_HEIGHT // SCALE + +thresholds = (220, 255) + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DETECT_WIDTH, DETECT_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_RGB_888) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def capture_picture(): + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DETECT_WIDTH, DETECT_HEIGHT, image.GRAYSCALE, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + rgb888_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = rgb888_img.to_grayscale() + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, rgb888_img) + img.binary([thresholds], invert=False, zero=True) + img.copy_to(osd_img) + del img + gc.collect() + print(fps.fps()) + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("camera capture") + capture_picture() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/12-Image-Filters/histogram_equalization.py b/share/qtcreator/examples/12-Image-Filters/histogram_equalization.py new file mode 100644 index 00000000000..1165539c759 --- /dev/null +++ b/share/qtcreator/examples/12-Image-Filters/histogram_equalization.py @@ -0,0 +1,109 @@ +# Histogram Equalization +# +# This example shows off how to use histogram equalization to improve +# the contrast in the image. + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 +SCALE = 4 +DETECT_WIDTH = DISPLAY_WIDTH // SCALE +DETECT_HEIGHT = DISPLAY_HEIGHT // SCALE + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DETECT_WIDTH, DETECT_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_RGB_888) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def capture_picture(): + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DETECT_WIDTH, DETECT_HEIGHT, image.RGB565, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + rgb888_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = rgb888_img.to_rgb565() + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, rgb888_img) + img.histeq() + img.copy_to(osd_img) + del img + gc.collect() + print(fps.fps()) + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("camera capture") + capture_picture() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/12-Image-Filters/kernel_filters.py b/share/qtcreator/examples/12-Image-Filters/kernel_filters.py new file mode 100644 index 00000000000..3c8294fd008 --- /dev/null +++ b/share/qtcreator/examples/12-Image-Filters/kernel_filters.py @@ -0,0 +1,115 @@ +# Kernel Filtering Example +# +# This example shows off how to use a generic kernel filter. + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 +SCALE = 4 +DETECT_WIDTH = DISPLAY_WIDTH // SCALE +DETECT_HEIGHT = DISPLAY_HEIGHT // SCALE + +kernel_size = 1 # 3x3==1, 5x5==2, 7x7==3, etc. + +kernel = [-2, -1, 0, + -1, 1, 1, + 0, 1, 2] + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DETECT_WIDTH, DETECT_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_RGB_888) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def capture_picture(): + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DETECT_WIDTH, DETECT_HEIGHT, image.GRAYSCALE, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + rgb888_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = rgb888_img.to_grayscale() + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, rgb888_img) + # Run the kernel on every pixel of the image. + img.morph(kernel_size, kernel) + img.copy_to(osd_img) + del img + gc.collect() + print(fps.fps()) + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("camera capture") + capture_picture() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/12-Image-Filters/lens_correction.py b/share/qtcreator/examples/12-Image-Filters/lens_correction.py new file mode 100644 index 00000000000..7fc05609477 --- /dev/null +++ b/share/qtcreator/examples/12-Image-Filters/lens_correction.py @@ -0,0 +1,111 @@ +# Lens Correction +# +# This example shows off how to use the lens correction method to fix lens +# distortion in an image. You need to do this for qrcode / barcode / data matrix +# detection. Increase the strength below until lines are straight in the view. +# Zoom in (higher) or out (lower) until you see enough of the image. + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 +SCALE = 4 +DETECT_WIDTH = DISPLAY_WIDTH // SCALE +DETECT_HEIGHT = DISPLAY_HEIGHT // SCALE + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DETECT_WIDTH, DETECT_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_RGB_888) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def capture_picture(): + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DETECT_WIDTH, DETECT_HEIGHT, image.RGB565, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + rgb888_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = rgb888_img.to_rgb565() + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, rgb888_img) + img.lens_corr(strength = 1.8, zoom = 1.0) + img.copy_to(osd_img) + del img + gc.collect() + print(fps.fps()) + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("camera capture") + capture_picture() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/12-Image-Filters/linear_polar.py b/share/qtcreator/examples/12-Image-Filters/linear_polar.py new file mode 100644 index 00000000000..a8de929ebb5 --- /dev/null +++ b/share/qtcreator/examples/12-Image-Filters/linear_polar.py @@ -0,0 +1,111 @@ +# Linear Polar Mapping Example +# +# This example shows off re-projecting the image using a linear polar +# transformation. Linear polar images are useful in that rotations +# become translations in the X direction and linear changes +# in scale become linear translations in the Y direction. + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 +SCALE = 4 +DETECT_WIDTH = DISPLAY_WIDTH // SCALE +DETECT_HEIGHT = DISPLAY_HEIGHT // SCALE + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DETECT_WIDTH, DETECT_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_RGB_888) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def capture_picture(): + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DETECT_WIDTH, DETECT_HEIGHT, image.RGB565, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + rgb888_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = rgb888_img.to_rgb565() + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, rgb888_img) + img.linpolar(reverse=False) + img.copy_to(osd_img) + del img + gc.collect() + print(fps.fps()) + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("camera capture") + capture_picture() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/12-Image-Filters/log_polar.py b/share/qtcreator/examples/12-Image-Filters/log_polar.py new file mode 100644 index 00000000000..52a185837da --- /dev/null +++ b/share/qtcreator/examples/12-Image-Filters/log_polar.py @@ -0,0 +1,111 @@ +# Log Polar Mapping Example +# +# This example shows off re-projecting the image using a log polar +# transformation. Log polar images are useful in that rotations +# become translations in the X direction and exponential changes +# in scale (x2, x4, etc.) become linear translations in the Y direction. + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 +SCALE = 4 +DETECT_WIDTH = DISPLAY_WIDTH // SCALE +DETECT_HEIGHT = DISPLAY_HEIGHT // SCALE + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DETECT_WIDTH, DETECT_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_RGB_888) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def capture_picture(): + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DETECT_WIDTH, DETECT_HEIGHT, image.RGB565, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + rgb888_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = rgb888_img.to_rgb565() + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, rgb888_img) + img.logpolar(reverse=False) + img.copy_to(osd_img) + del img + gc.collect() + print(fps.fps()) + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("camera capture") + capture_picture() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/12-Image-Filters/mean_adaptive_threshold_filter.py b/share/qtcreator/examples/12-Image-Filters/mean_adaptive_threshold_filter.py new file mode 100644 index 00000000000..c5375cdd591 --- /dev/null +++ b/share/qtcreator/examples/12-Image-Filters/mean_adaptive_threshold_filter.py @@ -0,0 +1,113 @@ +# Mean Adaptive Threshold Filter Example +# +# This example shows off mean filtering with adaptive thresholding. +# When mean(threshold=True) the mean() method adaptive thresholds the image +# by comparing the mean of the pixels around a pixel, minus an offset, with that pixel. + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 +SCALE = 4 +DETECT_WIDTH = DISPLAY_WIDTH // SCALE +DETECT_HEIGHT = DISPLAY_HEIGHT // SCALE + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DETECT_WIDTH, DETECT_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_RGB_888) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def capture_picture(): + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DETECT_WIDTH, DETECT_HEIGHT, image.RGB565, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + rgb888_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = rgb888_img.to_rgb565() + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, rgb888_img) + # The first argument is the kernel size. N coresponds to a ((N*2)+1)^2 + # kernel size. E.g. 1 == 3x3 kernel, 2 == 5x5 kernel, etc. Note: You + # shouldn't ever need to use a value bigger than 2. + img.mean(1, threshold=True, offset=5, invert=True) + img.copy_to(osd_img) + del img + gc.collect() + print(fps.fps()) + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("camera capture") + capture_picture() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/12-Image-Filters/mean_filter.py b/share/qtcreator/examples/12-Image-Filters/mean_filter.py new file mode 100644 index 00000000000..fe320130e75 --- /dev/null +++ b/share/qtcreator/examples/12-Image-Filters/mean_filter.py @@ -0,0 +1,113 @@ +# Mean Filter Example +# +# This example shows off mean filtering. Mean filtering is your standard average +# filter in a NxN neighborhood. Mean filtering removes noise in the image by +# bluring everything. But, it's the fastest kernel filter operation. + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 +SCALE = 4 +DETECT_WIDTH = DISPLAY_WIDTH // SCALE +DETECT_HEIGHT = DISPLAY_HEIGHT // SCALE + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DETECT_WIDTH, DETECT_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_RGB_888) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def capture_picture(): + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DETECT_WIDTH, DETECT_HEIGHT, image.RGB565, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + rgb888_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = rgb888_img.to_rgb565() + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, rgb888_img) + # The only argument is the kernel size. N coresponds to a ((N*2)+1)^2 + # kernel size. E.g. 1 == 3x3 kernel, 2 == 5x5 kernel, etc. Note: You + # shouldn't ever need to use a value bigger than 2. + img.mean(1) + img.copy_to(osd_img) + del img + gc.collect() + print(fps.fps()) + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("camera capture") + capture_picture() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/12-Image-Filters/median_adaptive_threshold_filter.py b/share/qtcreator/examples/12-Image-Filters/median_adaptive_threshold_filter.py new file mode 100644 index 00000000000..a5860f22a73 --- /dev/null +++ b/share/qtcreator/examples/12-Image-Filters/median_adaptive_threshold_filter.py @@ -0,0 +1,115 @@ +# Median Adaptive Threshold Filter Example +# +# This example shows off median filtering with adaptive thresholding. +# When median(threshold=True) the median() method adaptive thresholds the image +# by comparing the median of the pixels around a pixel, minus an offset, with that pixel. + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 +SCALE = 4 +DETECT_WIDTH = DISPLAY_WIDTH // SCALE +DETECT_HEIGHT = DISPLAY_HEIGHT // SCALE + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DETECT_WIDTH, DETECT_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_RGB_888) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def capture_picture(): + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DETECT_WIDTH, DETECT_HEIGHT, image.RGB565, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + rgb888_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = rgb888_img.to_rgb565() + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, rgb888_img) + # The first argument to the median filter is the kernel size, it can be + # either 0, 1, or 2 for a 1x1, 3x3, or 5x5 kernel respectively. The second + # argument "percentile" is the percentile number to choose from the NxN + # neighborhood. 0.5 is the median, 0.25 is the lower quartile, and 0.75 + # would be the upper quartile. + img.median(1, percentile=0.5, threshold=True, offset=5, invert=True) + img.copy_to(osd_img) + del img + gc.collect() + print(fps.fps()) + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("camera capture") + capture_picture() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/12-Image-Filters/median_filter.py b/share/qtcreator/examples/12-Image-Filters/median_filter.py new file mode 100644 index 00000000000..6fa5ff9a84e --- /dev/null +++ b/share/qtcreator/examples/12-Image-Filters/median_filter.py @@ -0,0 +1,115 @@ +# Median Filter Example +# +# This example shows off median filtering. Median filtering replaces every pixel +# with the median value of it's NxN neighborhood. Median filtering is good for +# removing noise in the image while preserving edges. + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 +SCALE = 4 +DETECT_WIDTH = DISPLAY_WIDTH // SCALE +DETECT_HEIGHT = DISPLAY_HEIGHT // SCALE + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DETECT_WIDTH, DETECT_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_RGB_888) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def capture_picture(): + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DETECT_WIDTH, DETECT_HEIGHT, image.RGB565, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + rgb888_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = rgb888_img.to_rgb565() + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, rgb888_img) + # The first argument to the median filter is the kernel size, it can be + # either 0, 1, or 2 for a 1x1, 3x3, or 5x5 kernel respectively. The second + # argument "percentile" is the percentile number to choose from the NxN + # neighborhood. 0.5 is the median, 0.25 is the lower quartile, and 0.75 + # would be the upper quartile. + img.median(1, percentile=0.5) + img.copy_to(osd_img) + del img + gc.collect() + print(fps.fps()) + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("camera capture") + capture_picture() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/12-Image-Filters/midpoint_adaptive_threshold_filter.py b/share/qtcreator/examples/12-Image-Filters/midpoint_adaptive_threshold_filter.py new file mode 100644 index 00000000000..a4a4dbde461 --- /dev/null +++ b/share/qtcreator/examples/12-Image-Filters/midpoint_adaptive_threshold_filter.py @@ -0,0 +1,116 @@ +# Midpoint Adaptive Threshold Filter Example +# +# This example shows off midpoint filtering with adaptive thresholding. +# When midpoint(threshold=True) the midpoint() method adaptive thresholds the image +# by comparing the midpoint of the pixels around a pixel, minus an offset, with that pixel. + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 +SCALE = 4 +DETECT_WIDTH = DISPLAY_WIDTH // SCALE +DETECT_HEIGHT = DISPLAY_HEIGHT // SCALE + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DETECT_WIDTH, DETECT_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_RGB_888) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def capture_picture(): + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DETECT_WIDTH, DETECT_HEIGHT, image.RGB565, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + rgb888_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = rgb888_img.to_rgb565() + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, rgb888_img) + # The first argument is the kernel size. N coresponds to a ((N*2)+1)^2 + # kernel size. E.g. 1 == 3x3 kernel, 2 == 5x5 kernel, etc. Note: You + # shouldn't ever need to use a value bigger than 2. The "bias" argument + # lets you select between min and max blending. 0.5 == midpoint filter, + # 0.0 == min filter, and 1.0 == max filter. Note that the min filter + # makes images darker while the max filter makes images lighter. + img.midpoint(1, bias=0.5, threshold=True, offset=5, invert=True) + img.copy_to(osd_img) + del img + gc.collect() + print(fps.fps()) + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("camera capture") + capture_picture() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/12-Image-Filters/midpoint_filter.py b/share/qtcreator/examples/12-Image-Filters/midpoint_filter.py new file mode 100644 index 00000000000..cc7c426c8b7 --- /dev/null +++ b/share/qtcreator/examples/12-Image-Filters/midpoint_filter.py @@ -0,0 +1,115 @@ +# Midpoint Filter Example +# +# This example shows off midpoint filtering. Midpoint filtering replaces each +# pixel by the average of the min and max pixel values for a NxN neighborhood. + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 +SCALE = 4 +DETECT_WIDTH = DISPLAY_WIDTH // SCALE +DETECT_HEIGHT = DISPLAY_HEIGHT // SCALE + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DETECT_WIDTH, DETECT_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_RGB_888) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def capture_picture(): + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DETECT_WIDTH, DETECT_HEIGHT, image.RGB565, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + rgb888_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = rgb888_img.to_rgb565() + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, rgb888_img) + # The first argument is the kernel size. N coresponds to a ((N*2)+1)^2 + # kernel size. E.g. 1 == 3x3 kernel, 2 == 5x5 kernel, etc. Note: You + # shouldn't ever need to use a value bigger than 2. The "bias" argument + # lets you select between min and max blending. 0.5 == midpoint filter, + # 0.0 == min filter, and 1.0 == max filter. Note that the min filter + # makes images darker while the max filter makes images lighter. + img.midpoint(1, bias=0.5) + img.copy_to(osd_img) + del img + gc.collect() + print(fps.fps()) + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("camera capture") + capture_picture() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/12-Image-Filters/mode_adaptive_threshold_filter.py b/share/qtcreator/examples/12-Image-Filters/mode_adaptive_threshold_filter.py new file mode 100644 index 00000000000..8b17cae93e8 --- /dev/null +++ b/share/qtcreator/examples/12-Image-Filters/mode_adaptive_threshold_filter.py @@ -0,0 +1,113 @@ +# Mode Adaptive Threshold Filter Example +# +# This example shows off mode filtering with adaptive thresholding. +# When mode(threshold=True) the mode() method adaptive thresholds the image +# by comparing the mode of the pixels around a pixel, minus an offset, with that pixel. +# Avoid using the mode filter on RGB565 images. It will cause artifacts on image edges... + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 +SCALE = 4 +DETECT_WIDTH = DISPLAY_WIDTH // SCALE +DETECT_HEIGHT = DISPLAY_HEIGHT // SCALE + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DETECT_WIDTH, DETECT_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_RGB_888) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def capture_picture(): + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DETECT_WIDTH, DETECT_HEIGHT, image.RGB565, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + rgb888_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = rgb888_img.to_rgb565() + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, rgb888_img) + # The only argument to the median filter is the kernel size, it can be + # either 0, 1, or 2 for a 1x1, 3x3, or 5x5 kernel respectively. + img.mode(1, threshold=True, offset=5, invert=True) + img.copy_to(osd_img) + del img + gc.collect() + print(fps.fps()) + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("camera capture") + capture_picture() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/12-Image-Filters/mode_filter.py b/share/qtcreator/examples/12-Image-Filters/mode_filter.py new file mode 100644 index 00000000000..fa63b142a74 --- /dev/null +++ b/share/qtcreator/examples/12-Image-Filters/mode_filter.py @@ -0,0 +1,113 @@ +# Mode Filter Example +# +# This example shows off mode filtering. Mode filtering is a highly non-linear +# operation which replaces each pixel with the mode of the NxN neighborhood +# of pixels around it. Avoid using the mode filter on RGB565 images. It will +# cause artifacts on image edges... + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 +SCALE = 4 +DETECT_WIDTH = DISPLAY_WIDTH // SCALE +DETECT_HEIGHT = DISPLAY_HEIGHT // SCALE + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DETECT_WIDTH, DETECT_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_RGB_888) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def capture_picture(): + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DETECT_WIDTH, DETECT_HEIGHT, image.RGB565, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + rgb888_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = rgb888_img.to_rgb565() + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, rgb888_img) + # The only argument to the median filter is the kernel size, it can be + # either 0, 1, or 2 for a 1x1, 3x3, or 5x5 kernel respectively. + img.mode(1) + img.copy_to(osd_img) + del img + gc.collect() + print(fps.fps()) + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("camera capture") + capture_picture() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/12-Image-Filters/negative.py b/share/qtcreator/examples/12-Image-Filters/negative.py new file mode 100644 index 00000000000..dde77acc7d6 --- /dev/null +++ b/share/qtcreator/examples/12-Image-Filters/negative.py @@ -0,0 +1,109 @@ +# Negative Example +# +# This example shows off negating the image. This is not a particularly +# useful method but it can come in handy once in a while. + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 +SCALE = 4 +DETECT_WIDTH = DISPLAY_WIDTH // SCALE +DETECT_HEIGHT = DISPLAY_HEIGHT // SCALE + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DETECT_WIDTH, DETECT_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_RGB_888) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def capture_picture(): + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DETECT_WIDTH, DETECT_HEIGHT, image.RGB565, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + rgb888_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = rgb888_img.to_rgb565() + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, rgb888_img) + img.negate() + img.copy_to(osd_img) + del img + gc.collect() + print(fps.fps()) + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("camera capture") + capture_picture() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/12-Image-Filters/perspective_and_rotation_correction.py b/share/qtcreator/examples/12-Image-Filters/perspective_and_rotation_correction.py new file mode 100644 index 00000000000..574b5a7fc48 --- /dev/null +++ b/share/qtcreator/examples/12-Image-Filters/perspective_and_rotation_correction.py @@ -0,0 +1,159 @@ +# Rotation Correction +# +# This example shows off how to use the rotation_corr() to both correct for +# perspective distortion and then to rotate the new corrected image in 3D +# space aftwards to handle movement. + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 +SCALE = 4 +DETECT_WIDTH = DISPLAY_WIDTH // SCALE +DETECT_HEIGHT = DISPLAY_HEIGHT // SCALE + +# The image will be warped such that the following points become the new: +# +# (0, 0) +# (w-1, 0) +# (w-1, h-1) +# (0, h-1) +# +# Try setting the points below to the corners of a quadrilateral +# (in clock-wise order) in the field-of-view. You can get points +# on the image by clicking and dragging on the frame buffer and +# recording the values shown in the histogram widget. + +w = DETECT_WIDTH +h = DETECT_HEIGHT + +TARGET_POINTS = [(0, 0), # (x, y) CHANGE ME! + (w-1, 0), # (x, y) CHANGE ME! + (w-1, h-1), # (x, y) CHANGE ME! + (0, h-1)] # (x, y) CHANGE ME! + +# Degrees per frame to rotation by... +X_ROTATION_DEGREE_RATE = 5 +Y_ROTATION_DEGREE_RATE = 0.5 +Z_ROTATION_DEGREE_RATE = 0 +X_OFFSET = 0 +Y_OFFSET = 0 + +ZOOM_AMOUNT = 1 # Lower zooms out - Higher zooms in. +FOV_WINDOW = 25 # Between 0 and 180. Represents the field-of-view of the scene + # window when rotating the image in 3D space. When closer to + # zero results in lines becoming straighter as the window + # moves away from the image being rotated in 3D space. A large + # value moves the window closer to the image in 3D space which + # results in the more perspective distortion and sometimes + # the image in 3D intersecting the scene window. + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DETECT_WIDTH, DETECT_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_RGB_888) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def capture_picture(): + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DETECT_WIDTH, DETECT_HEIGHT, image.RGB565, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + x_rotation_counter = 0 + y_rotation_counter = 0 + z_rotation_counter = 0 + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + rgb888_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = rgb888_img.to_rgb565() + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, rgb888_img) + img.rotation_corr(x_rotation = x_rotation_counter, + y_rotation = y_rotation_counter, + z_rotation = z_rotation_counter, + x_translation = X_OFFSET, + y_translation = Y_OFFSET, + zoom = ZOOM_AMOUNT, + fov = FOV_WINDOW, + corners = TARGET_POINTS) + x_rotation_counter += X_ROTATION_DEGREE_RATE + y_rotation_counter += Y_ROTATION_DEGREE_RATE + z_rotation_counter += Z_ROTATION_DEGREE_RATE + img.copy_to(osd_img) + del img + gc.collect() + print(fps.fps()) + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("camera capture") + capture_picture() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/12-Image-Filters/perspective_correction.py b/share/qtcreator/examples/12-Image-Filters/perspective_correction.py new file mode 100644 index 00000000000..da36f3821bc --- /dev/null +++ b/share/qtcreator/examples/12-Image-Filters/perspective_correction.py @@ -0,0 +1,129 @@ +# Perspective Correction +# +# This example shows off how to use the rotation_corr() to fix perspective +# issues related to how your CanMV Cam is mounted. + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 +SCALE = 4 +DETECT_WIDTH = DISPLAY_WIDTH // SCALE +DETECT_HEIGHT = DISPLAY_HEIGHT // SCALE + +# The image will be warped such that the following points become the new: +# +# (0, 0) +# (w-1, 0) +# (w-1, h-1) +# (0, h-1) +# +# Try setting the points below to the corners of a quadrilateral +# (in clock-wise order) in the field-of-view. You can get points +# on the image by clicking and dragging on the frame buffer and +# recording the values shown in the histogram widget. + +w = DETECT_WIDTH +h = DETECT_HEIGHT + +TARGET_POINTS = [(0, 0), # (x, y) CHANGE ME! + (w-1, 0), # (x, y) CHANGE ME! + (w-1, h-1), # (x, y) CHANGE ME! + (0, h-1)] # (x, y) CHANGE ME! + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DETECT_WIDTH, DETECT_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_RGB_888) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def capture_picture(): + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DETECT_WIDTH, DETECT_HEIGHT, image.RGB565, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + rgb888_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = rgb888_img.to_rgb565() + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, rgb888_img) + img.rotation_corr(corners = TARGET_POINTS) + img.copy_to(osd_img) + del img + gc.collect() + print(fps.fps()) + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("camera capture") + capture_picture() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/12-Image-Filters/rotation_correction.py b/share/qtcreator/examples/12-Image-Filters/rotation_correction.py new file mode 100644 index 00000000000..8789df09176 --- /dev/null +++ b/share/qtcreator/examples/12-Image-Filters/rotation_correction.py @@ -0,0 +1,138 @@ +# Rotation Correction +# +# This example shows off how to use the rotation_corr() to play with the scene +# window your CanMV Cam sees. + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 +SCALE = 4 +DETECT_WIDTH = DISPLAY_WIDTH // SCALE +DETECT_HEIGHT = DISPLAY_HEIGHT // SCALE + +# Degrees per frame to rotation by... +X_ROTATION_DEGREE_RATE = 5 +Y_ROTATION_DEGREE_RATE = 0.5 +Z_ROTATION_DEGREE_RATE = 0 +X_OFFSET = 0 +Y_OFFSET = 0 + +ZOOM_AMOUNT = 1 # Lower zooms out - Higher zooms in. +FOV_WINDOW = 60 # Between 0 and 180. Represents the field-of-view of the scene + # window when rotating the image in 3D space. When closer to + # zero results in lines becoming straighter as the window + # moves away from the image being rotated in 3D space. A large + # value moves the window closer to the image in 3D space which + # results in the more perspective distortion and sometimes + # the image in 3D intersecting the scene window. + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DETECT_WIDTH, DETECT_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_RGB_888) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def capture_picture(): + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DETECT_WIDTH, DETECT_HEIGHT, image.RGB565, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + x_rotation_counter = 0 + y_rotation_counter = 0 + z_rotation_counter = 0 + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + rgb888_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = rgb888_img.to_rgb565() + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, rgb888_img) + img.rotation_corr(x_rotation = x_rotation_counter, + y_rotation = y_rotation_counter, + z_rotation = z_rotation_counter, + x_translation = X_OFFSET, + y_translation = Y_OFFSET, + zoom = ZOOM_AMOUNT, + fov = FOV_WINDOW) + + x_rotation_counter += X_ROTATION_DEGREE_RATE + y_rotation_counter += Y_ROTATION_DEGREE_RATE + z_rotation_counter += Z_ROTATION_DEGREE_RATE + img.copy_to(osd_img) + del img + gc.collect() + print(fps.fps()) + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("camera capture") + capture_picture() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/12-Image-Filters/sharpen_filter.py b/share/qtcreator/examples/12-Image-Filters/sharpen_filter.py new file mode 100644 index 00000000000..7fca5b46075 --- /dev/null +++ b/share/qtcreator/examples/12-Image-Filters/sharpen_filter.py @@ -0,0 +1,109 @@ +# Sharpen Filter Example +# +# This example shows off using the laplacian filter to sharpen images. + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 +SCALE = 4 +DETECT_WIDTH = DISPLAY_WIDTH // SCALE +DETECT_HEIGHT = DISPLAY_HEIGHT // SCALE + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DETECT_WIDTH, DETECT_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_RGB_888) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def capture_picture(): + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DETECT_WIDTH, DETECT_HEIGHT, image.RGB565, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + rgb888_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = rgb888_img.to_rgb565() + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, rgb888_img) + # Run the kernel on every pixel of the image. + img.laplacian(1,sharpen=True) + img.copy_to(osd_img) + del img + gc.collect() + print(fps.fps()) + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("camera capture") + capture_picture() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/12-Image-Filters/unsharp_filter.py b/share/qtcreator/examples/12-Image-Filters/unsharp_filter.py new file mode 100644 index 00000000000..e43e89e3e68 --- /dev/null +++ b/share/qtcreator/examples/12-Image-Filters/unsharp_filter.py @@ -0,0 +1,109 @@ +# Unsharp Filter Example +# +# This example shows off using the guassian filter to unsharp mask filter images. + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 +SCALE = 4 +DETECT_WIDTH = DISPLAY_WIDTH // SCALE +DETECT_HEIGHT = DISPLAY_HEIGHT // SCALE + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DETECT_WIDTH, DETECT_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_RGB_888) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def capture_picture(): + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DETECT_WIDTH, DETECT_HEIGHT, image.RGB565, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + rgb888_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = rgb888_img.to_rgb565() + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, rgb888_img) + # Run the kernel on every pixel of the image. + img.gaussian(1,unsharp=True) + img.copy_to(osd_img) + del img + gc.collect() + print(fps.fps()) + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("camera capture") + capture_picture() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/12-Image-Filters/vflip_hmirror_transpose.py b/share/qtcreator/examples/12-Image-Filters/vflip_hmirror_transpose.py new file mode 100644 index 00000000000..1d4371906b4 --- /dev/null +++ b/share/qtcreator/examples/12-Image-Filters/vflip_hmirror_transpose.py @@ -0,0 +1,122 @@ +# Vertical Flip - Horizontal Mirror - Transpose +# +# This example shows off how to vertically flip, horizontally mirror, or +# transpose an image. Note that: +# +# vflip=False, hmirror=False, transpose=False -> 0 degree rotation +# vflip=True, hmirror=False, transpose=True -> 90 degree rotation +# vflip=True, hmirror=True, transpose=False -> 180 degree rotation +# vflip=False, hmirror=True, transpose=True -> 270 degree rotation + +from media.camera import * +from media.display import * +from media.media import * +import time, os, gc, sys + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 +SCALE = 4 +DETECT_WIDTH = DISPLAY_WIDTH // SCALE +DETECT_HEIGHT = DISPLAY_HEIGHT // SCALE + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # config vb for osd layer + config = k_vb_config() + config.max_pool_cnt = 1 + config.comm_pool[0].blk_size = 4*DISPLAY_WIDTH*DISPLAY_HEIGHT + config.comm_pool[0].blk_cnt = 1 + config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE + # meida buffer config + media.buffer_config(config) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output nv12 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DETECT_WIDTH, DETECT_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_RGB_888) + # media buffer init + media.buffer_init() + # request media buffer for osd image + globals()["buffer"] = media.request_buffer(4 * DISPLAY_WIDTH * DISPLAY_HEIGHT) + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # release media buffer + media.release_buffer(globals()["buffer"]) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def capture_picture(): + # create image for osd + buffer = globals()["buffer"] + osd_img = image.Image(DETECT_WIDTH, DETECT_HEIGHT, image.RGB565, alloc=image.ALLOC_VB, phyaddr=buffer.phys_addr, virtaddr=buffer.virt_addr, poolid=buffer.pool_id) + osd_img.clear() + display.show_image(osd_img, 0, 0, DISPLAY_CHN_OSD0) + mills = time.ticks_ms() + counter = 0 + fps = time.clock() + while True: + fps.tick() + try: + os.exitpoint() + rgb888_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + img = rgb888_img.to_rgb565() + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, rgb888_img) + img.replace(vflip=(counter//2)%2, + hmirror=(counter//4)%2, + transpose=False) + + if (time.ticks_ms() > (mills + 1000)): + mills = time.ticks_ms() + counter += 1 + img.copy_to(osd_img) + del img + gc.collect() + print(fps.fps()) + except KeyboardInterrupt as e: + print("user stop: ", e) + break + except BaseException as e: + sys.print_exception(e) + break + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE) + camera_is_init = False + try: + print("camera init") + camera_init() + camera_is_init = True + print("camera capture") + capture_picture() + except Exception as e: + sys.print_exception(e) + finally: + if camera_is_init: + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/13-Snapshot/emboss_snapshot.py b/share/qtcreator/examples/13-Snapshot/emboss_snapshot.py new file mode 100644 index 00000000000..7a7a513bd25 --- /dev/null +++ b/share/qtcreator/examples/13-Snapshot/emboss_snapshot.py @@ -0,0 +1,77 @@ +# Emboss Snapshot Example +# +# Note: You will need an SD card to run this example. +# +# You can use your CanMV Cam to save modified image files. + +from media.camera import * +from media.display import * +from media.media import * +import time, os + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output rgb888 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DISPLAY_WIDTH, DISPLAY_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_RGB_888) + # media buffer init + media.buffer_init() + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def capture_picture(): + time.sleep(1) + rgb888_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + try: + img = rgb888_img.to_rgb565() + img.morph(1, [+2, +1, +0, + +1, +1, -1, + +0, -1, -2]) # Emboss the image. + img.save("/sdcard/snapshot_emboss.jpg") + print("save image ok") + except Exception as e: + print("save image fail: ", e) + # release image for dev and chn + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, rgb888_img) + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + print("camera init") + camera_init() + print("camera capture") + capture_picture() + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/13-Snapshot/snapshot.py b/share/qtcreator/examples/13-Snapshot/snapshot.py new file mode 100644 index 00000000000..9656f264693 --- /dev/null +++ b/share/qtcreator/examples/13-Snapshot/snapshot.py @@ -0,0 +1,73 @@ +# Snapshot Example +# +# Note: You will need an SD card to run this example. +# +# You can use your CanMV Cam to save image files. + +from media.camera import * +from media.display import * +from media.media import * +import time, os + +DISPLAY_WIDTH = ALIGN_UP(1920, 16) +DISPLAY_HEIGHT = 1080 + +def camera_init(): + # use hdmi for display + display.init(LT9611_1920X1080_30FPS) + # init default sensor + camera.sensor_init(CAM_DEV_ID_0, CAM_DEFAULT_SENSOR) + # set chn0 output size + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_0, DISPLAY_WIDTH, DISPLAY_HEIGHT) + # set chn0 output format + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_0, PIXEL_FORMAT_YUV_SEMIPLANAR_420) + # create meida source device + globals()["meida_source"] = media_device(CAMERA_MOD_ID, CAM_DEV_ID_0, CAM_CHN_ID_0) + # create meida sink device + globals()["meida_sink"] = media_device(DISPLAY_MOD_ID, DISPLAY_DEV_ID, DISPLAY_CHN_VIDEO1) + # create meida link + media.create_link(meida_source, meida_sink) + # set display plane with video channel + display.set_plane(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, PIXEL_FORMAT_YVU_PLANAR_420, DISPLAY_MIRROR_NONE, DISPLAY_CHN_VIDEO1) + # set chn1 output rgb888 + camera.set_outsize(CAM_DEV_ID_0, CAM_CHN_ID_1, DISPLAY_WIDTH, DISPLAY_HEIGHT) + camera.set_outfmt(CAM_DEV_ID_0, CAM_CHN_ID_1, PIXEL_FORMAT_RGB_888) + # media buffer init + media.buffer_init() + # start stream for camera device0 + camera.start_stream(CAM_DEV_ID_0) + +def camera_deinit(): + # stop stream for camera device0 + camera.stop_stream(CAM_DEV_ID_0) + # deinit display + display.deinit() + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + time.sleep_ms(100) + # destroy media link + media.destroy_link(globals()["meida_source"], globals()["meida_sink"]) + # deinit media buffer + media.buffer_deinit() + +def capture_picture(): + time.sleep(1) + rgb888_img = camera.capture_image(CAM_DEV_ID_0, CAM_CHN_ID_1) + try: + rgb888_img.to_jpeg().save("/sdcard/snapshot.jpg") + print("save image ok") + except Exception as e: + print("save image fail: ", e) + # release image for dev and chn + camera.release_image(CAM_DEV_ID_0, CAM_CHN_ID_1, rgb888_img) + +def main(): + os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) + print("camera init") + camera_init() + print("camera capture") + capture_picture() + print("camera deinit") + camera_deinit() + +if __name__ == "__main__": + main() diff --git a/share/qtcreator/examples/14-Socket/http_client.py b/share/qtcreator/examples/14-Socket/http_client.py new file mode 100644 index 00000000000..4882afee386 --- /dev/null +++ b/share/qtcreator/examples/14-Socket/http_client.py @@ -0,0 +1,39 @@ +import socket + + +def main(use_stream=True): + #创建socket + s = socket.socket() + #获取地址及端口号 对应地址 + ai = socket.getaddrinfo("www.baidu.com", 80) + #ai = socket.getaddrinfo("10.100.228.5", 8080) + + print("Address infos:", ai) + addr = ai[0][-1] + + print("Connect address:", addr) + #连接 + s.connect(addr) + + if use_stream: + # MicroPython socket objects support stream (aka file) interface + # directly, but the line below is needed for CPython. + s = s.makefile("rwb", 0) + #发送http请求 + s.write(b"GET /index.html HTTP/1.0\r\n\r\n") + #打印请求内容 + print(s.read()) + else: + #发送http请求 + s.send(b"GET /index.html HTTP/1.0\r\n\r\n") + #打印请求内容 + print(s.recv(4096)) + #print(s.read()) + #关闭socket + s.close() + + +#main() +main(use_stream=True) +main(use_stream=False) + diff --git a/share/qtcreator/examples/14-Socket/http_server.py b/share/qtcreator/examples/14-Socket/http_server.py new file mode 100644 index 00000000000..8bb647116bb --- /dev/null +++ b/share/qtcreator/examples/14-Socket/http_server.py @@ -0,0 +1,81 @@ +# port from micropython/examples/network/http_server.py +import socket +import network +import time +# print(network.LAN().ifconfig()[0]) +# print("Listening, connect your browser to http://%s:8081/" % (network.LAN().ifconfig()[0])) + +CONTENT = b"""\ +HTTP/1.0 200 OK + +Hello #%d from k230 canmv MicroPython! +""" + + +def main(micropython_optimize=True): + #建立socket + s = socket.socket() + #获取地址及端口号 对应地址 + # Binding to all interfaces - server will be accessible to other hosts! + ai = socket.getaddrinfo("0.0.0.0", 8081) + print("Bind address info:", ai) + addr = ai[0][-1] + #设置属性 + s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + #绑定地址 + s.bind(addr) + #开始监听 + s.listen(5) + print("Listening, connect your browser to http://%s:8081/" % (network.LAN().ifconfig()[0])) + + counter = 0 + while True: + #接受连接 + res = s.accept() + client_sock = res[0] + client_addr = res[1] + print("Client address:", client_addr) + print("Client socket:", client_sock) + #非阻塞模式 + client_sock.setblocking(False) + if not micropython_optimize: + # To read line-oriented protocol (like HTTP) from a socket (and + # avoid short read problem), it must be wrapped in a stream (aka + # file-like) object. That's how you do it in CPython: + client_stream = client_sock.makefile("rwb") + else: + # .. but MicroPython socket objects support stream interface + # directly, so calling .makefile() method is not required. If + # you develop application which will run only on MicroPython, + # especially on a resource-constrained embedded device, you + # may take this shortcut to save resources. + client_stream = client_sock + + print("Request:") + #获取内容 + req = client_stream.read() + print(req) + + while True: + ##获取内容 + h = client_stream.read() + if h == b"" or h == b"\r\n": + break + print(h) + #回复内容 + client_stream.write(CONTENT % counter) + #time.sleep(0.5) + #关闭 + client_stream.close() + # if not micropython_optimize: + # client_sock.close() + counter += 1 + #print("wjx", counter) + if counter > 20 : + print("http server exit!") + #关闭 + s.close() + break + + +main() diff --git a/share/qtcreator/examples/14-Socket/iperf3.py b/share/qtcreator/examples/14-Socket/iperf3.py new file mode 100755 index 00000000000..996836396e9 --- /dev/null +++ b/share/qtcreator/examples/14-Socket/iperf3.py @@ -0,0 +1,582 @@ +""" +Pure Python, iperf3-compatible network performance test tool. + +MIT license; Copyright (c) 2018-2019 Damien P. George + +Supported modes: server & client, TCP & UDP, normal & reverse + +Usage: + import iperf3 + iperf3.server() + iperf3.client('192.168.1.5') + iperf3.client('192.168.1.5', udp=True, reverse=True) +""" + +import sys, struct +import time, select, socket +import json + +# Provide a urandom() function, supporting devices without os.urandom(). +try: + from os import urandom +except ImportError: + from random import randint + + def urandom(n): + return bytes(randint(0, 255) for _ in range(n)) + + +#DEBUG = False +DEBUG = True + +# iperf3 cookie size, last byte is null byte +COOKIE_SIZE = 37 + +# iperf3 commands +TEST_START = 1 +TEST_RUNNING = 2 +TEST_END = 4 +PARAM_EXCHANGE = 9 +CREATE_STREAMS = 10 +EXCHANGE_RESULTS = 13 +DISPLAY_RESULTS = 14 +IPERF_DONE = 16 + +if DEBUG: + cmd_string = { + TEST_START: "TEST_START", + TEST_RUNNING: "TEST_RUNNING", + TEST_END: "TEST_END", + PARAM_EXCHANGE: "PARAM_EXCHANGE", + CREATE_STREAMS: "CREATE_STREAMS", + EXCHANGE_RESULTS: "EXCHANGE_RESULTS", + DISPLAY_RESULTS: "DISPLAY_RESULTS", + IPERF_DONE: "IPERF_DONE", + } + + +def fmt_size(val, div): + for mult in ("", "K", "M", "G"): + if val < 10: + return "% 5.2f %s" % (val, mult) + elif val < 100: + return "% 5.1f %s" % (val, mult) + elif mult == "G" or val < 1000: + return "% 5.0f %s" % (val, mult) + else: + val /= div + + +class Stats: + def __init__(self, param): + self.pacing_timer_us = param["pacing_timer"] * 1000 + self.udp = param.get("udp", False) + self.reverse = param.get("reverse", False) + self.running = False + + def start(self): + self.running = True + self.t0 = self.t1 = ticks_us() + self.nb0 = self.nb1 = 0 # num bytes + self.np0 = self.np1 = 0 # num packets + self.nm0 = self.nm1 = 0 # num lost packets + if self.udp: + if self.reverse: + extra = " Jitter Lost/Total Datagrams" + else: + extra = " Total Datagrams" + else: + extra = "" + print("Interval Transfer Bitrate" + extra) + + def max_dt_ms(self): + if not self.running: + return -1 + return max(0, (self.pacing_timer_us - ticks_diff(ticks_us(), self.t1)) // 1000) + + def add_bytes(self, n): + if not self.running: + return + self.nb0 += n + self.nb1 += n + self.np0 += 1 + self.np1 += 1 + + def add_lost_packets(self, n): + self.np0 += n + self.np1 += n + self.nm0 += n + self.nm1 += n + + def print_line(self, ta, tb, nb, np, nm, extra=""): + dt = tb - ta + print( + " %5.2f-%-5.2f sec %sBytes %sbits/sec" + % (ta, tb, fmt_size(nb, 1024), fmt_size(nb * 8 / dt, 1000)), + end="", + ) + if self.udp: + if self.reverse: + print( + " %6.3f ms %u/%u (%.1f%%)" % (0, nm, np, 100 * nm / (max(1, np + nm))), end="" + ) + else: + print(" %u" % np, end="") + print(extra) + + def update(self, final=False): + if not self.running: + return + t2 = ticks_us() + dt = ticks_diff(t2, self.t1) + if final or dt > self.pacing_timer_us: + ta = ticks_diff(self.t1, self.t0) * 1e-6 + tb = ticks_diff(t2, self.t0) * 1e-6 + self.print_line(ta, tb, self.nb1, self.np1, self.nm1) + self.t1 = t2 + self.nb1 = 0 + self.np1 = 0 + self.nm1 = 0 + + def stop(self): + self.update(True) + self.running = False + self.t3 = ticks_us() + dt = ticks_diff(self.t3, self.t0) + print("- " * 30) + self.print_line(0, dt * 1e-6, self.nb0, self.np0, self.nm0, " sender") + + def report_receiver(self, stats): + st = stats["streams"][0] + + # iperf servers pre 3.2 do not transmit start or end time, + # so use local as fallback if not available. + dt = ticks_diff(self.t3, self.t0) + + self.print_line( + st.get("start_time", 0.0), + st.get("end_time", dt * 1e-6), + st["bytes"], + st["packets"], + st["errors"], + " receiver", + ) + + +def recvn(s, n): + data = b"" + while len(data) < n: + data += s.recv(n - len(data)) + return data + + +def recvinto(s, buf): + if hasattr(s, "readinto"): + return s.readinto(buf) + else: + return s.recv_into(buf) + + +def recvninto(s, buf): + if hasattr(s, "readinto"): + n = s.readinto(buf) + assert n == len(buf) + else: + mv = memoryview(buf) + off = 0 + while off < len(buf): + off += s.recv_into(mv[off:]) + + +def make_cookie(): + cookie_chars = b"abcdefghijklmnopqrstuvwxyz234567" + cookie = bytearray(COOKIE_SIZE) + for i, x in enumerate(urandom(COOKIE_SIZE - 1)): + cookie[i] = cookie_chars[x & 31] + return cookie + + +def server_once(): + # Listen for a connection + ai = socket.getaddrinfo("0.0.0.0", 5201) + ai = ai[0] + print("Server listening on", ai[-1]) + s_listen = socket.socket(ai[0], socket.SOCK_STREAM) + s_listen.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + s_listen.bind(ai[-1]) + s_listen.listen(1) + s_ctrl, addr = s_listen.accept() + + # Read client's cookie + cookie = recvn(s_ctrl, COOKIE_SIZE) + if DEBUG: + print(cookie) + + # Ask for parameters + s_ctrl.sendall(bytes([PARAM_EXCHANGE])) + + # Get parameters + n = struct.unpack(">I", recvn(s_ctrl, 4))[0] + param = recvn(s_ctrl, n) + param = json.loads(str(param, "ascii")) + if DEBUG: + print(param) + reverse = param.get("reverse", False) + + # Ask to create streams + s_ctrl.sendall(bytes([CREATE_STREAMS])) + + if param.get("tcp", False): + # Accept stream + s_data, addr = s_listen.accept() + print("Accepted connection:", addr) + recvn(s_data, COOKIE_SIZE) + elif param.get("udp", False): + # Close TCP connection and open UDP "connection" + s_listen.close() + s_data = socket.socket(ai[0], socket.SOCK_DGRAM) + s_data.bind(ai[-1]) + data, addr = s_data.recvfrom(4) + s_data.sendto(b"\x12\x34\x56\x78", addr) + else: + assert False + + # Start test + s_ctrl.sendall(bytes([TEST_START])) + + # Run test + s_ctrl.sendall(bytes([TEST_RUNNING])) + + # Read data, and wait for client to send TEST_END + poll = select.poll() + poll.register(s_ctrl, select.POLLIN) + if reverse: + poll.register(s_data, select.POLLOUT) + else: + poll.register(s_data, select.POLLIN) + stats = Stats(param) + stats.start() + running = True + data_buf = bytearray(urandom(param["len"])) + while running: + for pollable in poll.poll(stats.max_dt_ms()): + if pollable_is_sock(pollable, s_ctrl): + cmd = recvn(s_ctrl, 1)[0] + if DEBUG: + print(cmd_string.get(cmd, "UNKNOWN_COMMAND")) + if cmd == TEST_END: + running = False + elif pollable_is_sock(pollable, s_data): + if reverse: + n = s_data.send(data_buf) + stats.add_bytes(n) + else: + recvninto(s_data, data_buf) + stats.add_bytes(len(data_buf)) + stats.update() + + # Need to continue writing so other side doesn't get blocked waiting for data + if reverse: + while True: + for pollable in poll.poll(0): + if pollable_is_sock(pollable, s_data): + s_data.send(data_buf) + break + else: + break + + stats.stop() + + # Ask to exchange results + s_ctrl.sendall(bytes([EXCHANGE_RESULTS])) + + # Get client results + n = struct.unpack(">I", recvn(s_ctrl, 4))[0] + results = recvn(s_ctrl, n) + results = json.loads(str(results, "ascii")) + if DEBUG: + print(results) + + # Send our results + results = { + "cpu_util_total": 1, + "cpu_util_user": 0.5, + "cpu_util_system": 0.5, + "sender_has_retransmits": 1, + "congestion_used": "cubic", + "streams": [ + { + "id": 1, + "bytes": stats.nb0, + "retransmits": 0, + "jitter": 0, + "errors": 0, + "packets": stats.np0, + "start_time": 0, + "end_time": ticks_diff(stats.t3, stats.t0) * 1e-6, + } + ], + } + results = json.dumps(results) + s_ctrl.sendall(struct.pack(">I", len(results))) + s_ctrl.sendall(bytes(results, "ascii")) + + # Ask to display results + s_ctrl.sendall(bytes([DISPLAY_RESULTS])) + + # Wait for client to send IPERF_DONE + cmd = recvn(s_ctrl, 1)[0] + assert cmd == IPERF_DONE + + # Close all sockets + s_data.close() + s_ctrl.close() + s_listen.close() + + +def server(): + while True: + server_once() + + +def client(host, udp=False, reverse=False, bandwidth=10 * 1024 * 1024): + print("CLIENT MODE:", "UDP" if udp else "TCP", "receiving" if reverse else "sending") + + param = { + "client_version": "3.6", + "omit": 0, + "parallel": 1, + "pacing_timer": 1000, + "time": 10, + } + + if udp: + param["udp"] = True + param["len"] = 1500 - 42 + param["bandwidth"] = bandwidth # this should be should be intended bits per second + udp_interval = 1000000 * 8 * param["len"] // param["bandwidth"] + else: + param["tcp"] = True + param["len"] = 3000 + + if reverse: + param["reverse"] = True + + # Connect to server + ai = socket.getaddrinfo(host, 5201)[0] + print("Connecting to", ai[-1]) + s_ctrl = socket.socket(ai[0], socket.SOCK_STREAM) + + s_ctrl.connect(ai[-1]) + + # Send our cookie + cookie = make_cookie() + if DEBUG: + print(cookie) + s_ctrl.sendall(cookie) + + # Object to gather statistics about the run + stats = Stats(param) + + # Run the main loop, waiting for incoming commands and dat + ticks_us_end = param["time"] * 1000000 + poll = select.poll() + poll.register(s_ctrl, select.POLLIN) + buf = None + s_data = None + start = None + udp_packet_id = 0 + udp_last_send = None + while True: + for pollable in poll.poll(stats.max_dt_ms()): + if pollable_is_sock(pollable, s_data): + # Data socket is writable/readable + t = ticks_us() + if ticks_diff(t, start) > ticks_us_end: + if reverse: + # Continue to drain any incoming data + recvinto(s_data, buf) + if stats.running: + # End of run + s_ctrl.sendall(bytes([TEST_END])) + stats.stop() + else: + # Send/receiver data + if udp: + if reverse: + recvninto(s_data, buf) + udp_in_sec, udp_in_usec, udp_in_id = struct.unpack_from(">III", buf, 0) + # print(udp_in_sec, udp_in_usec, udp_in_id) + if udp_in_id != udp_packet_id + 1: + stats.add_lost_packets(udp_in_id - (udp_packet_id + 1)) + udp_packet_id = udp_in_id + stats.add_bytes(len(buf)) + else: + # print('UDP send', udp_last_send, t, udp_interval) + if t - udp_last_send > udp_interval: + udp_last_send += udp_interval + udp_packet_id += 1 + struct.pack_into( + ">III", buf, 0, t // 1000000, t % 1000000, udp_packet_id + ) + n = s_data.sendto(buf, ai[-1]) + stats.add_bytes(n) + else: + if reverse: + recvninto(s_data, buf) + n = len(buf) + else: + # print('TCP send', len(buf)) + n = s_data.send(buf) + stats.add_bytes(n) + + elif pollable_is_sock(pollable, s_ctrl): + # Receive command + cmd = recvn(s_ctrl, 1)[0] + if DEBUG: + print(cmd_string.get(cmd, "UNKNOWN_COMMAND")) + if cmd == TEST_START: + if reverse: + # Start receiving data now, because data socket is open + poll.register(s_data, select.POLLIN) + start = ticks_us() + stats.start() + elif cmd == TEST_RUNNING: + if not reverse: + # Start sending data now + poll.register(s_data, select.POLLOUT) + start = ticks_us() + if udp: + udp_last_send = start - udp_interval + stats.start() + elif cmd == PARAM_EXCHANGE: + param_j = json.dumps(param) + s_ctrl.sendall(struct.pack(">I", len(param_j))) + s_ctrl.sendall(bytes(param_j, "ascii")) + elif cmd == CREATE_STREAMS: + if udp: + s_data = socket.socket(ai[0], socket.SOCK_DGRAM) + time.sleep(0.5) + s_data.sendto(struct.pack("I", len(results))) + s_ctrl.sendall(bytes(results, "ascii")) + + n = struct.unpack(">I", recvn(s_ctrl, 4))[0] + results = recvn(s_ctrl, n) + results = json.loads(str(results, "ascii")) + stats.report_receiver(results) + + elif cmd == DISPLAY_RESULTS: + s_ctrl.sendall(bytes([IPERF_DONE])) + s_ctrl.close() + time.sleep(1) # delay so server is ready for any subsequent client connections + return + + stats.update() + +#udp client ok --187 Kbits/sec +#tcp client ok --249 Kbits/sec +#server tcp-- 250 Kbits/sec +#server udp -- 187Kbits/sec. +def main(): + # opt_mode = None + # #-s -c + # opt_udp = False + # # True False + # opt_reverse = False + + #opt_mode = "-c" + opt_mode = "-c" + opt_host = "10.10.1.94" + #-s -c + opt_udp = False + #opt_udp = True + #True + # True False + opt_reverse = False + + + + # sys.argv.pop(0) + # while sys.argv: + # opt = sys.argv.pop(0) + # if opt == "-R": + # opt_reverse = True + # elif opt == "-u": + # opt_udp = True + # elif opt == "-s": + # opt_mode = opt + # elif opt == "-c": + # opt_mode = opt + # opt_host = sys.argv.pop(0) + # else: + # print("unknown option:", opt) + # raise SystemExit(1) + + if opt_mode == "-s": + server() + else: + client(opt_host, opt_udp, opt_reverse) + + +# if sys.platform == "linux": + +# def pollable_is_sock(pollable, sock): +# # if sock : +# # print(sock.fileno(), pollable[0],sock) +# return sock is not None and pollable[0] == sock + +# def ticks_us(): +# return int(time.time() * 1e6) + +# def ticks_diff(a, b): +# return a - b + +# if __name__ == "__main__": +# main() +# else: + +# def pollable_is_sock(pollable, sock): +# return pollable[0] == sock + +# from time import ticks_us, ticks_diff + + + +def pollable_is_sock(pollable, sock): + return sock is not None and pollable[0] == sock + +from time import ticks_us, ticks_diff +main() diff --git a/share/qtcreator/examples/14-Socket/network_lan.py b/share/qtcreator/examples/14-Socket/network_lan.py new file mode 100644 index 00000000000..5bbda94a410 --- /dev/null +++ b/share/qtcreator/examples/14-Socket/network_lan.py @@ -0,0 +1,38 @@ +import network + + +def main(): + #获取lan接口 + a=network.LAN() + #获取网口是否在使用 + print(a.active()) + #关闭网口 + print(a.active(0)) + #使能网口 + print(a.active(1)) + #查看网口 ip,掩码,网关,dns配置 + print(a.ifconfig()) + #设置网口 ip,掩码,网关,dns配置 + print(a.ifconfig(('192.168.0.4', '255.255.255.0', '192.168.0.1', '8.8.8.8'))) + #查看网口 ip,掩码,网关,dns配置 + print(a.ifconfig()) + #设置网口为dhcp模式 + print(a.ifconfig("dhcp")) + #查看网口 ip,掩码,网关,dns配置 + print(a.ifconfig()) + #查看网口mac地址 + print(a.config("mac")) + #设置网口mac地址 + print(a.config(mac="42:EA:D0:C2:0D:83")) + #查看网口mac地址 + print(a.config("mac")) + #设置网口为dhcp模式 + print(a.ifconfig("dhcp")) + #查看网口 ip,掩码,网关,dns配置 + print(a.ifconfig()) + + + + +main() + diff --git a/share/qtcreator/examples/14-Socket/tcp_client.py b/share/qtcreator/examples/14-Socket/tcp_client.py new file mode 100644 index 00000000000..007fcda380a --- /dev/null +++ b/share/qtcreator/examples/14-Socket/tcp_client.py @@ -0,0 +1,41 @@ +#配置 tcp/udp socket调试工具 +import socket +import time + +PORT=60000 + +def client(): + #获取地址及端口号 对应地址 + ai = socket.getaddrinfo("10.100.228.5", PORT) + #ai = socket.getaddrinfo("10.10.1.94", PORT) + print("Address infos:", ai) + addr = ai[0][-1] + + print("Connect address:", addr) + #建立socket + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) + #连接地址 + s.connect(addr) + + for i in range(10): + str="K230 tcp client send test {0} \r\n".format(i) + print(str) + #print(s.send(str)) + #发送字符串 + print(s.write(str)) + time.sleep(0.2) + #time.sleep(1) + #print(s.recv(4096)) + #print(s.read()) + #延时1秒 + time.sleep(1) + #关闭socket + s.close() + print("end") + + + +#main() +client() + + diff --git a/share/qtcreator/examples/14-Socket/tcp_server.py b/share/qtcreator/examples/14-Socket/tcp_server.py new file mode 100644 index 00000000000..b2b81ecd92a --- /dev/null +++ b/share/qtcreator/examples/14-Socket/tcp_server.py @@ -0,0 +1,68 @@ +#配置 tcp/udp socket调试工具 +import socket +import network +import time +PORT=60000 + + +CONTENT = b""" +Hello #%d from k230 canmv MicroPython! +""" + + + +def server(): + counter=1 + #获取地址及端口号 对应地址 + #ai = socket.getaddrinfo("10.100.228.5", 8000) + ai = socket.getaddrinfo("0.0.0.0", PORT) + print("Address infos:", ai,PORT) + addr = ai[0][-1] + + print("Connect address:", addr) + #建立socket + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) + #设置属性 + s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + #绑定 + s.bind(addr) + #监听 + s.listen(5) + print("tcp server %s port:%d\n" % ((network.LAN().ifconfig()[0]),PORT)) + + + while True: + #接受连接 + res = s.accept() + client_sock = res[0] + client_addr = res[1] + print("Client address:", client_addr) + print("Client socket:", client_sock) + client_sock.setblocking(False) + + client_stream = client_sock + #发送字符传 + client_stream.write(CONTENT % counter) + + while True: + #读取内容 + h = client_stream.read() + if h != b"" : + print(h) + #回复内容 + client_stream.write("recv :%s" % h) + + if "end" in h : + #关闭socket + client_stream.close() + break + + counter += 1 + if counter > 10 : + print("server exit!") + #关闭 + s.close() + break + +#main() +server() diff --git a/share/qtcreator/examples/14-Socket/udp_clinet.py b/share/qtcreator/examples/14-Socket/udp_clinet.py new file mode 100644 index 00000000000..d3f03d29b8b --- /dev/null +++ b/share/qtcreator/examples/14-Socket/udp_clinet.py @@ -0,0 +1,38 @@ +#配置 tcp/udp socket调试工具 +import socket +import time + + +def udpclient(): + #获取地址和端口号 对应地址 + ai = socket.getaddrinfo("10.100.228.5", 60000) + #ai = socket.getaddrinfo("10.10.1.94", 60000) + print("Address infos:", ai) + addr = ai[0][-1] + + print("Connect address:", addr) + #建立socket + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + + + + for i in range(10): + str="K230 udp client send test {0} \r\n".format(i) + print(str) + #发送字符串 + print(s.sendto(str,addr)) + #延时 + time.sleep(0.2) + #time.sleep(1) + #print(s.recv(4096)) + #print(s.read()) + #延时 + time.sleep(1) + #关闭 + s.close() + print("end") + + + +#main() +udpclient() diff --git a/share/qtcreator/examples/14-Socket/udp_server.py b/share/qtcreator/examples/14-Socket/udp_server.py new file mode 100644 index 00000000000..68e0eed6283 --- /dev/null +++ b/share/qtcreator/examples/14-Socket/udp_server.py @@ -0,0 +1,45 @@ +#配置 tcp/udp socket调试工具 +import socket +import time +import network +PORT=60000 + + +def udpserver(): + #获取地址及端口号对应地址 + ai = socket.getaddrinfo("0.0.0.0", PORT) + #ai = socket.getaddrinfo("10.10.1.94", 60000) + print("Address infos:", ai) + addr = ai[0][-1] + + print("udp server %s port:%d\n" % ((network.LAN().ifconfig()[0]),PORT)) + #建立socket + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + #设置属性 + s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + #绑定 + s.bind(addr) + print("a") + #延时 + time.sleep(1) + + for j in range(10): + try: + #接受内容 + data, addr = s.recvfrom(800) + print("b") + except: + continue + #打印内容 + print("recv %d" % j,data,addr) + #回复内容 + s.sendto(b"%s have recv count=%d " % (data,j), addr) + #关闭 + s.close() + print("udp server exit!!") + + + + +#main() +udpserver() diff --git a/share/qtcreator/examples/15-Utils/db/readme.txt b/share/qtcreator/examples/15-Utils/db/readme.txt new file mode 100644 index 00000000000..a8f1f8dd323 --- /dev/null +++ b/share/qtcreator/examples/15-Utils/db/readme.txt @@ -0,0 +1 @@ +用于存放人脸数据库 diff --git a/share/qtcreator/examples/15-Utils/db_img/id_1.jpg b/share/qtcreator/examples/15-Utils/db_img/id_1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0cb764acf1ad8828072c16af83ffac80467d4904 GIT binary patch literal 15136 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 literal 0 HcmV?d00001 diff --git a/share/qtcreator/examples/15-Utils/db_img/id_2.png b/share/qtcreator/examples/15-Utils/db_img/id_2.png new file mode 100644 index 0000000000000000000000000000000000000000..95372a281bd32c6e6d10df23a0f7c12f910fcda0 GIT binary patch literal 188132 zcmX_ncQjnz_qG-#I*Hzi5}i>8qa=Du1kp>PjNUt=iy#Q1527UzEk-Y+6Kxp1wmW>O{gjt0#|Z0ykA7PYevI7ynI6wYMBc7#Qec zwO0!7{LJ_6uTws1_$tW3l&+mKK^f+A;6S937Z>B{ zhcgn@{kS7_hwNw!m6U49P-H`tL#N~(UyXD)A{-E zuk!ta>2&z~FrwCk2g1OM%57H&4*X>DfZDH^(x3byx1Vozr|m1@{WSML+c5?`9_@3s z`!Wp_!>=+6+Iy+B+P=T-XFm4>(+iC5ea~S`d(gBH!5K2T z&vw7^rl@|@Jbsl-BH2*%MKMZ&~lzaks`iYv+TuAG? z5<|0eZkp^PUIFcFXXBB!GKEf1UwghjcZ49FSNRl4y%UUg+pzI=h0m>_85KWTl2XeH z0op&$%Oys19+cDw$U$+?rNsN&mwbCJ(meN`#v6dyMK7Oimu9y`7vFL4fq(<<{?3;B zNqX0f>`=|(!FP6;%gMsz^D|e?5_ey{4~$z!r6`aTLWF6nIosS#lGiiDbo6+`Lx&c< z#VB12*&3ydK-)ysh%9XpG#U6@Le+V))jCi3qlfdIqr94;&IueT_VX_ZJm(Cqx{C5$ zxwy|@tD-sqMKj=g*f_^r!L;(2 zfLz_lDEh`^SsJBqk4unZ?6?F7-fq1MjJvXn@;O8JGvW1J=Q&a!@N+gEX<=ggK5BizF#Z8%Ky{&SOo2 zSZ$!c^fnLE2-XuOew^2RSG8dlKCH*ERex#zFKQ1-$r#!1#q`O7Dw76%bHI2Bt6u`;NIdRpvV2DQv}YOcwzB@`bUAbbn#Io} zu5F^IW91g1eFKJ1d@bprC1x`8d7`t&E560v#iuGv*H zqsykpE@+VFm7BOCRbJDc+>psE%h~Mcf4LI+gkA(}H~tlWp*UUHM2>5Qam6ANf7$+U zzN9gHq0nbfNlu^*diK7ze#~c&>fz($&eFZheJvk|Kvu!N{^+)-{!QH=oU!Z5#<*bw zCP_>=9KXRan$f0X;#)5#W@cVLWS@4tdr%_V=P8OFPc5c}CFF^M*i&~aX<-hKkHcZ^ zJE0+7RLw+tfN;iCUxr6>H{AKSu2sa$Au}LR!+4JV5m?vU)Q^7S8$wFo8@soV^kvSU zV~NS5Vcn^4qEk-59N41cuth%We&N0`{oz~tBisnqSApLav(j6ul4$SU>ngR#-M`d` zGXEH_u7bamJYu<#Z1eX4f^z>0Z&D28WI}CQ1Ou8kuuTq2h0)HB+#t~I+^Jf=<4@z4 zZ(>3NCLMZ<^|dR0i~oS-9{6>hk4fJ~OkiX2j~K~-{pPm#q|4!@#7Kg;QYF(t?)qIG zoxrBp(i2>(rcw#+PjrG=6c&+ zMbjmxwFAsklT@ufm`}BSCu?5^ySgGS+(%KRB-+N8eI4%SysYjgj#6{tU&SveVC*L~ zf*i)TAk?B(`4QKyC+irk458v$QP4^987Wg`lH{7XjIS|d1CXs4qi7AsX2o1t{FyW0 zHWNZZ8Dt*SowD(=G_+4&3jW(o8@@#^{f|`V_rtu%1vUQ2t*)nJ8s`|vz*laGigEEj z+R}u#X`+CXe>zPaqF)9_`OsX%xgm%GqL{1sUrL--B{otEl$@@87$ba4)_%B`P$*NT z%NH8IJefk-yM|;M-zhd8D#tJTZJN{CDfX|?3kN2`zdVc+P@;RqQ} zSMos4*^2wr@yB3E?P5~8ERIGd)q}6+R(wyK@9ZK(9<+{k-HOOeESW(v$?xX%l|@74 za=(;hbr`w%Gp(u(d$p?m+uhw&$G(>Z+gAw^ljI} zt89rmzRhEZ^+=!iO;`f}N!kw>@(z4I!lku5V&&^QO^3y~t|j#cl@f|^)LBKMmh4cA z?MP$KSe{R*g=H_H`m%H~LoVx8`VlXJFg2Wh;BfdTkQ@+ez?CzW8BG39wQ+94B-HrT@dU$M@wl|l?Tv~mVAK8W zLfDp16ABO&WO@WUg)FV6M}^qqH8%%>?d$}dou@ya$1?fa4&+V?VjPGCnCF|?z~hI} z{?2e%vlH~icGhx05aDzJA*i(ccVB^8D#3#4o=>-HDM|f9i$kE+_nNbLC7{+Chxh2` zkT#48Rkl*^_u310S3`>B2BHbAEM`LtZ(dkk=oKe|fBXs5RC=R4@W4S`5vDB`E9oAb zp~}B=R!=jbyJd51(&eCq-r6`*MPg?*Y&&b@(<~^17k_&m(i$_ zc(fYo#uQ8;|KUln{t@gX_|3}elI0b7*I(}x$@UKZyl)lkAP44>G41YVgB{CW5=VTY zR}}VL*-Ch369mb;!3<*RntN5VwXTUvm@S$yF5f6OfEBT&jCsP>&Yp$yhvKh0RkLZk z=BIJMsE1ANlYzKt+Voy^`zN_y&YEYG{!XslKIN({abi{-mi+NE{?BRP?3B*V!A|Wy zc@OR0BS;_ZmEkE46cgCqnfnIvc-XGKFt!j;U4nUxMJPGp-`ul;E@ z0_TDK*zUtDKPfHzcNihLZN{K%5-@6U{N=?Im2xy5vg9u2AMVOhpZF9M3TvzTdaw-7vprnY@${?-u&BX! z?{_t7lf{syT7S5tmM&l}7GhXop&t?qLtJHsb$R&R^PR$%Ojvc+9f^FxOP z#G-iqnrur&A_sw4d|jCMV^9({ilL`rRGJ##d6G*dPJ`~4UXc@#2U`2M@_aLNa1iD6 zaG3OauXo28$=us2M+UaOdPKRkU& zI^xw&B~`!uP|3;rcjO~z9r5kujf@W@VgT-0fSG zH4ZJ}VgL7hX}5a)sI+tHG-i*7LN=E=axJ2EDEL(MCo&VKp+Ss4o8yRNsj> z5z!8zTs(hvpGfsCx_8O%N;`<+4{?jC;&&&zepE=BA{ICNbf&_Oc#JuWT0xZo55}L7 z>sK5Z8G;iJm5q7u3oK{db2%&`PZ+81K2zx)^7Zja zbrB;bO(;1(PXk<98f0}X0&Z6n0$6G!CG4EPa|#5WZYIE58ZuloXvkcxod9O70mF2C zN85fk*MdvwmPRltAxX&`T$SkY+Fc3cMwubf7k=6b2tHP%%gy=2VkL`R0vb&$d7}Z$ zHUazF2oKAeR*5S%GvwtYMc1T7EBD3Uu8f90%|UKC zgLjbhI{35p=+pKW^|cEZ5z!QFs!%g3*(0`3eHt$j}2bb7&` z7KjG$K|J>Q$@`J7n$_jLbSLO)mzrhS*i)bRQ&Gr2K%+8Sm}+th4E6-VPd_}DLDWWX zRtYMMnm7T&S34SvRPv4X)$z|R^^rR}4!_QNR9ot5oO5vT@b=p(t***V>XBP{L0PtT z%tdL%8?d^%Zw}4Ckwd~pi$)Kg{aB;Q^70aA;q$N#^{mXSZ=2QoKZ~!gpH%9YHhJ+7 zt9DuL*jsx@6KiDTyPLLoyf*HO0>EM1GPua3$o?q8bYzILVDK@D3l%5WcJywXx3a~$ zB$j1|I>h4kX1-G&>owy3{{E-Q%QwD>Ggw)XodpV2jMNoe_&2O0D0tiE`MQYf^B3x0&Fm?OrHY&e0vj9=p6YL4J-wvzI80@S=r~VDhu`9Nm6xGF0f|Mpo@azzwjVPqt%wAIRWUV?XNe+rdHpwY6?33UW==IRoQxxrF;prMz&T{v1(!Q zh)c3KTl>wJ*}1#VW+}Pav|qQKPtBtSCd;0JcnSd7Avf!J0m2OX9geK@Ca4;OT+PMt z&TeIK9JOHSzJr+l%jY_-2?<)Nx~dVhbRHqM6!%e`)>@#;s^ymUTaz zFZ3M!6{Y%LJadx#s@&h#ma=+?`r-V=wO9FcH930C0^)d>0)G zvWw$^8aMf`zepSvG|xH~D2|OKa3ngt+~VUS<6ik}Thm&@!&=R%^^vRf4mk{vm4dni z9~YMvzQ0?VG1W;IG}RPrJ^3?k88e<5i4%;;@Vk1?H_-51F=Uh|@Rijj6%}&2?cy9D zCbsdD`{=d@u_PMu9Q+hNA#9a=z4He5s_o&19@Pe5K+@&X=&*NvppwS_6i4yCNae*E0=sb)DY}i^=kf{*y{W%C%50{O=_K;+%JNO;h_X<+aK}5otRBn>4Y1sua z7$3^Zs&FHf;FM12sP+9xp%X8MaiImG%=F7TG+V(0{m9|s(7y>{O`)3JQ>m8|N#G$q zp+J>H%gUGKR=&LDBTE{<`CYKTm9T8kRn^FmaQtW{TUKVKn&|lW6q99zJ!WJN#3qEt z+0`|${Cm@&^pm(AvE&zXJyEEi0Ju=PLHf)?Q!-WecBN_K*S6~f-*M!?A3(VKx@b|d ztfT;cc~R|f!i~!>s2mt$;I=s3LhJHiQA2N>ItN`=*|t-6Jf4S^;TPzBMtw**E;>aw z`gH0AO-YF@GWYh9PuGo^kyZm+DZ<>aBWTxT`J3|Ou7}o$W+@L?vw@w)VW;HQ0e;=i zAV%z8lZ3&?@ouDvlZ(?G_WG69L}ombN4B`kx+0deZNGE%0;f(F{C~if_lke{KVbV2 z?a@Iq6S}>nIS^XAb%T8U5(K$D8=nWA)q3T(lQlwu1Q^S?Aqz*SvP`JYhU4xsC)(#Y zPmPt8YkPo*7wAuhFSOF8uCud$aEv9C)rq{j2V8F0fjzxv3*BfWS7~Mod8))i>4|8s zdL`Pd!sIhR_v0Wf6ZO)j)|8vT+eo`a%s&VVD{D)0>t*lSxunZQ7l3QpKIhKOn*@ga$67j zBV<{2O7GfAJ2!grcFuHJeY(P;zRJXCS!fCWyW@0)k!k`rWR7!}HXAs<S}%cR z8(Kg_%^H1ViFwe%tJS4{Shz1NkG}J3iAd1LlHY%uZ?_60o%Uo+UQKdkU}N0>XU}$J zH@-cMpZhE?l@-!k;FP7n{*c=0$x7~$FnX#3L0jBg9W!M3U<^NfFP^Jd1~~fT8W&BX z@aM0tb`4|n{s8hRD8C$HmB;u+5I8D;_8Ap#Gk&R{OE!~+lj#Vg3yb@yf767l%Q$#g za-o~rZsaVv(d}G447r*{tzr{=y7e8mV-8L-NT=qI6z>)S8Dia{Hqu?ycP*R2I>shu zYV#)9sO-ZKc486|)!i8i&wX{!RR=_q*Lq5W@D%Le!A49>2}n5in~n^^?0!QwVxY(FNal8s-pCRN&1W$j9gwR$>hlo7Yf2y=VgOhJ1 z5^Aa8jS;fSted(!wnooX#(4~5&GVBZ_-M^UasFN*z}mj_XX>c~t~0L3eu38P{KhiL zT+ikA>`+W%6UE!^)PSC%_xZM%0YOf$hJNqx|6&fg3Ynvdi27OnTcG$7a!~{GL)QVq zC(q6+A&Z3vyL7=RTLULqosf*S+r`6@!F0jW^q%*b^>+WdvwH0Ef~_!xir+k#dr#{r z4GzZHZfgn_Fb<6@=}cFcUx0U9Lr&?LdR$#y1J2rnKzVH!7xSI9z{OUGPJECAzxwvO zdf!%(s>Vj=1l)wMpj*6{-_8s0%l779@6#JDki+j57d1flD4o`;1hQEQ0Zo2)A=jWF zQ!K}66A#yg_;b=JX6~-#+dv4yo#xnm<%k-76;;}pA-|aF(+wMUDd*%b%xb!Mi7YYK zLH~8VQx4c#^fiN;d0S;DxE2E^Cvfs5P;8X}!6$e4kNLQGHPW!~>MANvt~$LTVy4fTe=-zJz;i0efO>1Sjv$>zDe zeM0TjI;uHjBCCUGV_7}*F&B#8{UmW0B(tW+2}1jI3{|T}+MBT7JGnXm@A`Ei?%j4E z{zvwqBlp0)IHj6dsIWUYNQE1pdbre<)^zEEq_1rK8gg3?nUB9u(UBAGI%H<>X?TnW zT}0H;pD{ueLe9oiP;14!sBxXtgRMM&lid|dxF^Q~wMEE5^25P_c2mg4pHko6UKN>Q zF=5tT!Gf9>(Jf7F-!|>G#=ijw0H3r7YGp}wiSf|~a)*|5G&CpQMHN4I+YEz`LN*3! z&*rjSRay9p;a?4ufR@9U4CEvXoy~!l6;B8^uFIG2ZmGz;v=^5B*2^t-Y9qXKjGxc@ z1s45{Pt+>00#gaMrt&qAaQMxh1e$>#27KFi6Sn73ojq~i55ja@KV%Dkx{#F(cEcU- zJXqtPq6k0)g;gOwC)r2(T#I$av2ln@_@`2AO2Gqf>R9=_8w7{HW;04!tc&Z83Z_&u zm1cxU7r7R^$o<%)_LoX$xPZLcj##%r`)MQJhKRRulg}AgrA=FmHa$No6$N{kORwbJ zuU6%A=`ffIdypeM7(SnbwFn)8OY{?twwUEq^@WEl?*8?mYIH#Agw}QIgOSIu%7;$PKvZdce{4WYKy-$csiOW|Hp{V4yAVuq|U#cW#>OW~6)`8cxf^q)shh zs!AAl+B2s-+*x3fg*DV*(xByVh8~evI@T_dTD>S<^U$_-v*%7AN-V)7V2K>fhu(5H zZTl@Lh`}?arp2GK3cdQ-D&JOXrX^-22E5dz>-v&;0z278?P@ueIid;^L3Qn)o?HsA zNA!lWWap-puoJIO?E|50bd2;`l*rFM#pLn$c(8;JlEt4+=^SJ;BF!AcsIXdS!^H=$ zj{pE=f8~+vcRe`5dfUwV5AW*4VxhQNYqxD)g$KYwd)iy9h;H6CS?q9^Knng>x$XAXmoi#*=<|N5x zsyE@KJRIHeb@k#cxIzF)7GlM@u9KjELpzWb=wWQRBykxXm2v&0!GND%z08u>`W?~z z&Ez2Jrq&UaMPpYP*+KfS>8j`KYQg?bgQ>W((zPg#y0S>Z93om?QSSJvH79`g9(=KC zYHVz-c6osKte}qZt|#XOnWSHz;_<>l3lMkSl$^{fTw*CmwDtaCdatdvHB;{TECt5N z+I=16XjoY)SKQp%y6Y$$5XieUhLd9UZBss@u`%jQ*A{H^qWt&o(({DjNYlN^evsPL zJAEGjE{XJF5b8OYV;<_!39;Q&yqUDP*KP{fci4H3jV^@T9FVf?nyJOE|0 zKC=u;3OVayR;RoX3Fgsq1cQa0)g7%0f($o45`R?cyzFQNBIl;~U)jE5N7~3nbsp?Z zAhl~twmuf%l8#`78GNn%Oq5&u<>GEVR;l!fpK`m`yXO8Lsi3Dn9I0fs+-_q18jjnu znLqpPodjOR&?B^;C914^O7i=MV}T9(K%qlF5*4}flYro4Q3Kmr7aRMYPRrGy8_lxV z8VoGw6ZqjiiOi>&wMjU#XbN~iO!_V;M1kT3@!5Io-^X$2z#+GlEHnNtQEd^U#5ox<5O$Y0j&iH#k>B zBti~*%f4GyN^BjNDL!S;Qn-C{ zP7l^6$~pgJ)B|S;6Bd?&F5PcR$WC@+F>jGqm^DKW78)IgKj@gDG$sS4HI20xTX7PO5;Mg^&$V;FF0vaA_Qk(5&erD`+eAZn~9 z!0dLe!WWx*?$CUTYP|%xNo5?Yu`EW+8i8L?{PI04wYXc8EtR?zs@qWXhT)eSz7)Cj zFflg&x{`#U=TF9DvDB1uFr;2%YXrWpsJ>ROc2=A4 zD6$|osXr^X{)Bqvqz@j(1D+CaL%{w{uln8d-~m{?syt`9B;^^b_!a(E5_z*KM1T!H zdEg@0WDXTO^M!B<<+Sa}FfGfTUw^OU>|EnGR|(*l;QQE}=+){MZDJMFtuYtwXV3(> z)V{e(N#p=HfNcZV%3}-euMR^}ZJ8G|1eb$&9+^H6tf!e%o<(hIOQ9HAUXm7OCA_8u zCJ09LYDkFv$-C_MQ`vf2N8_j!AE5Q%NY~?9((HS{y^Ni(fV#DM(D_q7Xpu@J{J_MdZ9b8 z9SOyH6xJ=D#*Q(BM>DD}E;{{Wgz0AG9u=@1fQzS&703#7c zGO|(|T38x{aa2?vkW6Ip8l8?t;l37Lw2XAm9=go)SmL*e3bNMT#8vD%ZEbZvtMqpB zd^zd=A=L5^2aE1Q9?`%ZSN&uPY*splf4&cQ|BvgS1>wz&(Z*(@c?e%mJw~#L?2Ehm zFT+4NAqWnRiL%=e86pP2e@n1)pi;2q8**rIUmywy2e3Sm=_RY6jF_9}TXa%?4Wb9A z)r{c?Z2b8MXW1*bMJ2rb*=5BJ0yxj9a*&OE@mZmqBkH#H)sR%4<)%K&D8%<7EU4%_ z>dRG-!XbL0Qd7(Hh8(kn3l%sEyxVn|8NVs3M=(px}R!BK^`m~(r*@3 z|4Z(UxU)KtI|F}cE<*vSOa!zEb6hdw`+}hJ^sObo_2&d%jGMT$qIy;#cZulgtuwry z_)7Cehmw|-hSZ0vMD+W@i+S6X-!WcWwvyngb&l(>VfspV@)G1wDbMqLO0*($Lai9-8dg;%Ga5cBWMDAO zkwj%`sJ|KUu8j$7mj1d~NA7xpj&%1qeoI(EnAiD@*x`zzeKndftmEC(QGXJ$qG%Np zOgA}vwz5?2bs2{UcAcCVO`;ylJW+~Mv@9?ioo;Mu)j*b1A~*JHHara{nw`Tx{QIiq zGLdO9F%OJ*_COLbG0d7e|8bVP0*gtcx-f~_JW&*|hN1aFBdH=RO$(D)GpEM%P7jq;WFyzNCxH|V=fNnEZ$6tj!LW{WF(jI4ECZSV1S zm(&`H$02d3!|TpD2zmhD>>i?vGp1hAr3+a)#Ezk3m|N22zS$m+%v(@XLb~)`F-Who zwK__;6s24Ei`}oak|LvN1T~M#D_c?XZ)-@RZDGq?nNx3dZ~xvreAI>0;%e!8>su=o3@F}3ZYw(^AlIuIRkd7sSTW8ASa zTiY|jb&^2;;R7!}-c@w;&5P7;??C!sa-=awm95mUK*w+ZsTVC1qXxT@EZFW+KK$3W zo0};3j;p`3hDX!1^V+93i|j0+d$^4_`{3q2S2wcO~0>yzLgA< z*$xt^_=fcSn3vq|&J`(#f&8CT_Oyd&7ddIacCK=XMcm+wXNXCBfu|+0Gycf zUVYmVSe>sVw#Z|1qWySuZN@<3ra@Fzg?5cbc7skHUwl54*sc9xW%}$<8b56 z8&*Tk3Yn#d?c1B4bcWTCk77B8jw6bc0*bQd@x>cV^vEjqLe?l0Mxv{#w1OfTu`u&L zP%>q)a|^G8H|yjGR%AdODZDNZmoyIV|Jk7g(RYGKW;6l~KTBc07ux^r`r_X!{qX9# zR>9$j4IN_qIhbAxy&c0`kH0BKf^jA_C0#jJX zGO+fuvlomj(4swz=F@;(1QCpc8$MqLJ#iAFPts~Wc))!&vxwl{ z1c)i-Y2^h!#cs|OpK8>ICEOMN*POQ$vRm%8J~@qqW=zYYLzR!yVBDA;_loEZ$g#!M z{8OQsjUF5D6Q?ax38jD5ZH&U=8B4`+=`99Fu^AlG9__!S{3HN?72ubv5}Zq^YO>(n zIE2^$la_1i^*5EtZo915udUac*>Y#mWZ79+K63a(G?L>0A;T$30gJX&POee_1@ncM zuCHO<6U^|quAtvBD~b85h4S`_3qw0R{H=l-k}NFmMOUim=J1#q6fNC0Bm6MV+XHZ} z?PRuR@QGoJZMrdTMbYo=OZeVEvj*dnR-i8f38-2w62)fIQway>^?fM*+8iwBOnEC%c1VIBOUXb&LfPLQIH%bQg%Sgv=jsxlBgQfs$kRd|*`3&{PnY0l(A%*UYc^nZIbSn>qHFOtL zjBaL!g$ORu2_>!)(G{hKRtI1(1qPpT&1U<=P{&dQoHRJ@P|?-3q*&k7EmaSp0HxZ!QcZDuKoA%EZ7gOYJuh=Vj+%Q~i zyru55K{wOh%0TYb)60 zaUx5;&kKgSZb0S(fwGG&NaR2#>AQl^bFm^=!}kwreu9-1#bE`jfWoos3zFp$Cbjfu zuBM$)i-ruN>nu#b&MQtFMT`PWIecn+45dD0mQ|7zyO;L9^)F@Y=`mNn=vwwsWZ{W- zhKtd5R%;Mig_6BKI*KnK8qGN)uiNWflj-SL3NbeOrd;3=+VyD%M*;pfycGv8hG-ex z6Nmym^gvWWcaLRn(gT5C*G%0it`qS>OT+Inh%`mTw8e6}PM-+f6K!k}H2|^>JTa3o zIq&^e{EKJ>_&!{W*U5>E*I8R<&{sWl7OoW zC7pkMtWu-(id6}*$MuiYX?QP5 z&GUKWGgT<_+!H$D&Um*KCI5cHY>)Q4%rDLE>(NhoFX8Cmd3*9v+>UrMD?3W8K;3h% z!x1xx-Up?I-}uYS_vfTY^d;mDT?D_Y0bLq>v&2_<(p7`w|1mH}Dkh}^4BlAO@@AvH za4%szEp*?ix|S-N0IdABO&@2~#NBKMK5FA_76v#Ywv;-wI@#7|?B^8xS4$cH2}#M6 zm@(~-%Vt5=>2Pd@9>h;L5qDqeMoR;b*>F&MY6=v&aEG1ex$-iBe!5YhSt5b>)NHc= zR^7I_%R2K$6d;sSXE=onJiK4f(+NtvNqpE&L`t+hcpuJ$p}M&LuC7KHAvQb}uXZ-d zz@<%veuu^M(-oyL6e4k_$K}y+NRqZkd1TD%kHT%(!c&*a5J8%IWcXXf)7AMYU&<}F z_w6?C&^3AYnl|dFG(+=?cM}>CuJ*9D7bWNl>LT=}YY4Y;kkMTK@EI56q|~+{5AyK( z<~R}Ju=!L}Wzg@Eei^V&rkdk+Hm7V#U9?ofTNv z?~2T+-9~-k9h{vkqT<`PLo^&Ezc|@6p)|cbE(Ua$5AzrM4>#AeyL%NGcG@ER;u8&# zCvzp^SR^a~KY2C{Pb8lf%d6x!0?)mRf}zM)bTJ6|MxC_9Y=!0r!|2{Sq3#i|rNrjq zNDi*Y75lNymk`E*rU^+(c$(_R7rV*E(x!A=jBTkzcZ$u20VMk-9KS1 zQs*7C3UMmM=k5a?G(Lxs`cA;#sFKMdx#@%)iJz=|4wcXTb*OILbywYi-SPuYsByntquJ40Jzk1)^ zxnFOK(e5_O7|GdzCAjsRjLEd)cr_-k;qI~FRapYLJbY+%x7k5iptC`LfO?>!2n=~Y z410Fa^F-LxKa7zaX*cldEy&sl`Hc?mC>R8g7O zA>_96<4z1%IG1hem4i_rN0yvtDv~T`ql)j}aq%B16t27iURV8q^BdQ!3=h|KQHW%& z*64q8oM;?~&}lG-2gqt^C2D9aXx?MrQyF{41&MxmhgD`TsFH2ODE*wGX!NP}oX&vT zw-6tSesJ2jQ*>~RTOxK=@w`Bck0e73n$pB~01FeCy@fS%<8Sc613J|GbNl3U_4b%E z1~>wXUQiu4f8!##NRbp+>nvQrPcMf7tFHTCerdMbcb9%Nh1pl_{(88#8y znPY$MyHy)^vhJ+zBwQC%sY^rfw>4(iAh|0;feqUw@Cjwt1pR^9_BL}TU(ev`kc1YV-TgGrbp|V z>>q7YwSe|S5aZL|O6*XTJe{`>3>A%11pi<^1T(b6*Sc(37{1Pfei+BCm^=w;x3dip zG0V!-=GBNZ&!eFd-HH&8H#e%GVWRPw6SBwPscZGmC@hI&`a^KvfBk^%L zglK9h6Ty^i^B79jXM^>nR{!Yf9c@2d9xiL-Ju192|7{FX4?iO(>$bB>_k1#0?p%s~ zxIJ`?ls&Y|5R!cJB@slT6)iaK9=p=oOq#l68*n;YS$v4@gBv{D+jfuQVfH8r!@>w^ z)<2)TWtsx@r`S=oj0t4)c04A@RsO+Ye{4BPSujqhjMwZ~73BUA>WVM4zgSO{|4<$g z@Sz+FLvTT@S%Z$rSI+%&)*w!SU2*F4)zuF`qE$LUXm61Eb7waXrv+-!gZ(L_&cngs zqpV8ZGo`M&rpHX5M=L?+hp7|43$ache_=8yxWz{N%6wjpOM{CGEDtL z7~CL;zWm0PH(LptpE$!_$&#G*+qhV#at*y7{_`KccANF2)DW&xxP%O3&|b3#0@8?q!uPw8<(ApSB3pBD#GWAbFV|BKO}p_|b(y zCsNQ&`!VFIi&@$%Ly&L~pUYlYL}ata68So5_0j}>ZelKK)s4WE+Pt4OkU;hjnyv~v z7qr{y!LQhGp2z3r8e$A(pCpR|LRo8WKe+om*2gY$uJnFQ zbU!l5I*R}^OrA{^xtevdc;5GM?CByhJKSj zWv7!$!Mk2+44hwuoEt(W=WsNim)vHSss0QB(komP4ZxuhMHD)pVe z9WfRzqEw&Up{T>2@rFGgUxlv4j^0W$hmR~@mWal8flL$QTF+&TEc#A0v8sVJhs@HR z8{c?fcul-B$_WU_z?+3jyZ3)10`k9*85pgzS{#Kzshr|8+U|~)AF@H}kP|M* zS7ltitQ-cZ5XB_-V``B%@B; z7n!gtG5k-!tm*rhz3)wr;L@dmaoxJMwkmfl!GjKZ9PVRm0lB5OJ$dAc#mWz&6!!YX z)!7DyWDeLrUlMOk8d^{nnxsS@do=m_ikoFLW-zIL3cduwU789p`Cg)9V~=4qwaJe> z_o4R5>doA*%*PTr9=hH0MCc5DyP7D|TEnIgDSk4Q?V8mAIiB4rAlDN07G2|!h-`Nh zgs-{Tv&J8BarNydTFPfs6Y}ARP~Y}EqsQBo`JT?I1ruLtG>^Plqgvz>8pS0uB`rQa zc4vMc|Ow2#8|ts z&1+oo3VjVhLyGe5|7|VN2yvJH5%ZG9Jip?s8i+q&&?Zed+r2(~)JHwA7LpQqj@g&l ziS56)s2M0+pCUeVj;Ba2_sXEZ6g{vG3pjdC!JnUF7%ighMBB~V;%?WSz>r|4c_A3X z9cr3kayh!!SShw!|1R@4&P;=e`19Wyp~YpwltT*aWZ>$B57Nckr0{Po zthFXnz`P|XK(eZ?H4V2{8QD5tk34rY91qJdge(7aqyxLSI+r%rA70rS$bqDVrIJHV z#`FA$!xAr-c}tWmp%Oh_xZT}k_@1O&*8B8^}pOAY>|Jy^ylacYAW$+%D9y zx8={DRJl=A=oX5nVsA!+^cfWRwIS&cS?q|K+HXcBOfM(r7mUhk!|O{y`x;8WTnzQ{ zpybMe@H6!rX0!#`Rrsy&YOcf0xdj?}Y!@h)H6BGcj)Gi1wlrw&J_cC$f44d+V5&=y zn-E>@+4L;CJXk*0<{jay;kjkK^gwF58+51c3stf%7N6_CWV+XlXLhHIc$EO7(y-qj zkZ!lDWw8z3J^D+bRka;2nv9I88hkeE-5wIumfgZ?`;rreSVCW=a^iK~h=tqbTKoHm z*R`nY(d5$UkjgzsYT3U-^!Z**opjxjF4%)^uPD7=z7Qlyv{h8Go*4KP&oZ)blmiUv*04t6*{!K(j zbwn^p{CVldqblh3$!ZaKb;jhQp0@7fP|G5S$;5Qo@4ozO3v!VjYx0(}mvekj5T3Ji zdo4Khso?Kbx9ZJ-FMOZ;^0N465+38XpleHVM-B$d4^Kb8k>}I%q;Lp zR8Psg?IR_QeQkvt)Qk~>{ss$8QtrE20LZ%x88K{Ag|KFe!fX}j{t?QOv)Nic`GQaA z6Mei|)S(V9y`FhjW!FpEx@KU!W;wmiOFGh zpC^u|=Pip>bU&G9VD_AelAge2*_4v;JksFh80cJmP5Eq!BnzWH4=XiL5f4SylB zMe_5o;f$nE-*%9ZCOs||R|796L6^0wT=Tb+&X*58{c+bj!XP2Yp%8XqszP8vW)JnLXs zPBrM+Pn}LX2ixA${rToeKz&2f6u?8}Q+rP4iPc1F8P>bV^#+=o*1*g0e-rP1?Yn=@ z2bwkbN%8YnmXNo_bG1mlzqEr~a6PJ-pOpMR0LMT$zt=d|!4wxC|M^ef#i}ZyCLR$W$T>*;j_~-Cq!V6Wixx=+H8IF5?p+F;h?_ZZ~#v%p*lVH?`FyR>n z2h*eTb3q&tHP6A5E^7lY zkh~kHyloSJ?u5gJxxs`L56*NOk)XFqotSSw<{PuL733!X0+J9z{$ zJ&!Z(pjn)PO&jeJ+W@l+s){a573N?vBVA-7!^BtxM~~b z_wmP{nn8M7>7Bb`v||!1T#qqpjo|*>2R=W*3FMxxUQh3!HLz$sdv7-FRrk`=UxA{)2EGOWc5a@6IjZ)$dzq=cT>yksj`<+L4A+ zllIcJzbC;f;fhWooA;bI(@1C(*xZ#>Rd~w46qC36roH+IpRK=)+7AT-jD&#<%$g4p z@ev`Wcr>!FptZ!B0Djs3(8N>_3*TGP5LikhO&EP#vA%Xh*udoL0!BFHcXpXAuPmmG zwN)RQ;+$mWz91MOhQ0R)kg?GT zk6KwXxN_y1{3aZSGzrJ38fJ;$Asku&qgLfzk1(+2qFM0Gd5A%S4X+e&#y z6M#{|1n~pNi)k>@L<7k}gm~b9|F8YpuUX*X&pWrgB2*A4;K#{r(xW^u!+dir1_q1p z;d8BdbWT}Z_VH2Eg>=Xl{O~6ZaY>u7;FFm%%$hvv%v+ip{#kfqc*o??CMIhb*$zWm z-Su)p7vf~h!OpT=}GV4BJ79+4tOIpV2a?*iEP$EriJTHwU*xb#y8XFU))Ly zi_2b1;o5UX<*&SQ(>B+T@9pne16WyIvd|(7v=%G(^v-}Zj-lZ}3pfPF`kLYhzj1}- zM%zmlE{diSUbk*p@Wy>tp}D~pV8C8cmm77%mR0V-!tm@nc~wprH#W4uEr-L-24PWC z-T;CQrcWa{)E?Mc%iw^kL)e1LA-)hqtXITEf2>bQU`vaDmR!ZMzPe%!Yi{w(H7P$G6?ZlnC`oCob?~bSlQml^d){z(8Ow?06c{h?oV^4?pb=`tNgyDPW<#`fOkz0tb?+V!7y{0C^2 z27cMUS-5ujKkslH|9@gaA``r9a^pS;5I)=4qjRpU?nmR< zuX!PTRayvI5CVxZE-cPV%h0G_BVM+CE{kb%VC|wt^5Dsp=1`3LjJD;zEdj8($=yYK z^E!47adu%;%pcNn;Ek)v+4{=$BZMcN_$G%sj_6$7sY-KLvk>DO4lqovM(4_I1PRQR z@CXAKEoTbYBFj5<>5n`Wb%tHx%!IU){7!t{a~Reephq^;DTZgxJ8)?s_3kzxqVkPx zw6#5z1E8GLGiw&4J2V(Otg5?QZ@%p^p%I}S?J2JiBrK-)r47*v;qv|mAE@0(XsBFV z$x>CB__!3;zUO=of%ij*^F*aSQR;7Dj<)AU(+_ zG(>OQ%yi_%VkBo6_?VFRotc~DM%oqw;Djv)zW9JXJ6o8RVOj{La#dObBlu50jU7H0 zG$LP@K)8SJuGc8Ir^zEr#bxBp2%X(MFWmcha(Qyt_FgJN2T=Rs)< zFTebfagd|Z=er3S#fk}WmZM+7gL4EhZl=VTqT!^or-;n^VABtO(8;9DUl!b(tCc-pR6Wn0*5Ho8gFiFaTJ0o?NXC9q*i;>s% z#V{pg_y`eh&<>3Rrb-^Pe}@%~sFz3TPW6^sPlP+V3#zP1;0KO`12;4(+{=s@!C_6N zhzHXrOm9&(@Fz_)2G%6F@;wBQ@>YDbLdpQm5Tak+y5+6JT=@b0(3JXAUwp)f!-XE0 z9BKcD;MR5li!~|fTT~yFyGC# z)qKJl1JHS41~3VjN@gr(Hfk3z2=4D$SzJkTv-1)r>()9Z)cHBVyTu4q3}I&aq69=- z(#PWRgNO5JVQD3;Xtc_C27k|5BkExe@pv?1(9&QA|%w zq>1qnf5@n}hiS2z8tkshu_w1Kjd&~m(j81(nb>_mLIY#LAq@hd$TjBum0s`4VXb0a z0%B`(-FdwI<{RFngK*)5^`6SmE1Ws;JRk-KO`rq2fDmNtCgQ#-1P&wk*j^gDjL=pP zbbOa#x5o9{Ov}XLItLFC$m|#sVm7hI*jyKN;@Uhks=yt2A+&GpUt1M3bvhk!vy9ZqMl{s8W50H92iSBaTM)Lp*}SAFbA+hR>*Xn^g_ z)%58{AEyuBd*4^G=WVoTM<<2@5dd=z&joy?ngmc51dXQAzZsOnHNt7oZ*|=Zl6&y(>2^Lgy3L4o83$78d=cN1O4P68TYX!VosJkyt~?(@arEhv`|9;S{r{mBQpOga@#5nq}di4Q1Jt zkdE-tCbF=A*u-P~!R`tZno)#Dv!EV^Wde%$B!#f^Gpjf>td!O?Xy8EOsOtIGzxTa# z>B_XSh|3DW;}9a9L&)!q?gbpl^t%#AY<+?LAi zshgX8+~=n23n4NwF_k7Kr_-g&7ZSUHMn>a%1zdS?^)h$kq7t@N6caFyO;f9;_BkihHw| znzX=Fy!B$&84Lq$3GHHYopl@XtHwa>78w_V`84;5 z5(0;E!sI7L#}ePcKp;RL+8*@4@XSab8(Lxr;{{$ZP}~`n=jl7>!I=>JdCzG;lYI6d zv?tayVmA{&SYO4Vv@;I4ksrbwgIf;Eds!R6k9eeq;T;<{@<9kthY0mt22VNZ860uv z9e3P#Cw(b5o(`k#7%;Gt?Aq0I7#qxEx6Ujg4*p#1#%>*^k{F@ZYWqGp%`@ML7!`wKrw>8}!NC+0aq)-IAV9d2 zi0K~Y$T^5cT3i-4Gdblv5L5^UF1o{HVN#KH!CD4l!&jGUw2RPSePL`=BlVGCuN@2x z_W4`{+6e0u(~}cs{LK3wNGsujI;NeNf?6*2_%lN1TNE%n7V{~09&MxXc;3Dm=SDai z0p64iI^hN*2AH!4SHKKjv}3`T-9o$4P+-Jde#e;t3{z%4a7I4LgEJrHGZ1KPK0sFs zApi~0=%_(sxqL|*}9lA(mv>@RiBDc#}k+% zmQK6)?eOcAerN+hMNE^#4%9it41q`S*J#dLQwo8A=HL()6jBJ$8sR^ge%{4R8NeK~dw`CoIwE7S*N`u2<2t8~Tk)b^TiLJ6M&f>;G zdCl8HHL4aZStH?oCV#g9dLnFu2it?kMn@92vEmQ?VB+~gKGN8fh66CAgFwK}#^(!U z*mlbF4FH`mFmGsyK?vk`=$@H9Zadpmmy=;1rEybG{g9l66=kV$ULv+bbKN@SV(N)< za=kkmA8lc4O9KeS-BozD)q-!ow1^RD5v;=qv9z?ZlvX5w*%gPt?&}ln$42Glm5Txz z+i-qwbT8l-=aWKE?(A^bmkyuHZciG%%DgfhDW}?0hO&Ft?e$vS2WHX=Jc4KeG}czo zDG}%xt)Sq8X9gO0D`w7Op`P80r2p)H^IxWSzV)sJmnuVbA3N&C#-x3&a}I;k>cW!> z5XA2xusGfdT(2zvy|5D~n(>(-*Wp>AUHRGp?Wq--f+vj89HmUkn69SVmdRr`lR~Zl<4Tn)W&!LHg;9^9MHUWDVW-5nhU@an^{jM|_<@-!acPwt_ zX(LWEoBq;#uxTGKZo=@+^(Xt#UVluT#cr}br)L_<&^C7!291pL+1<9Qu;4pB&K+E% z-W`Q-}4`t>OtzG%0rwgi2573cbm8`f44K)t=JJM~#0 zS>xHuZ8aKi{30}zTz+W*ZTU}OpA|&5rwX0&$FdIB49?1*&xJ$@+M(AD|HmODB20wi z9;ASy@pyx&5fs}(LkxnEE)5+<#~e8a(O`(i3r68)B&Hz-!L-8S!h#p7(Kt4@HZ&6D zx`} zXr#;OW|)02ZG;U%0|t3u28-4L-lRubXhGOqG{>68=Gv;YC8m(3CMP`I14BeJ2?pNd z=@&Er4(M?Tnk%o_f(yffq5I2fVt6oEWg~$V^X}lo)K(S_(1bOTSTBfaJ*JZQLYx^n z!b0KM#)^R8i*FU>(bE@9n!|K3YEG%MQ%Hq2lea*CX)8Qsqjq5W-u0yPVCJ+3@F5(h z*+WP(-347@;T!zW7HABlN%;^U2ow4wEz98~1c-B>dSfj`O(F5wS-y!)cn(NX?+ASh z7s{%9W15j~bH^G~P4({sc4`9_CZb(oF4W z$Jss?679>^4xXrxh=v%Qs}-E25cRa4fN7V0r>%q}T7mOu0i6noL+_$I76G};RI*s-=YlqekmE+v=@_;Wg!PR}S8 zM#pqXY|RWNi#yrn1#iHkTj9eg?H8>5H?ZwAv{Qj^vJ_*);vNGP!^F)S{MQ=(nFKTbp+(J z&<+s>_(u$8n! zuO0p!3yGoto^CP}bI*EmOnK+$Fm&R>XQl!a!wk4q+Y#Sjnn=u6-5WPA#7e{9;N0@! zVtV*+HZ9K0#TUnv$lbelyf`~OHR;hebN*-?umG3=JT=x8Gzu4!Kttes0n;<2X@4_z zC3dg}Cow(<5EvL!9B30Uy%alrd}cv;F>3erSEhaxpWQ*8!coKKUA)Gc23Kz&WH?Yq zTK?oGVG7z2)~h*UmQc|44DAV;c6qeJza5Z7D{vkypi?11BaI;XIZy|M zc@%(q6i=Lr=0NXd{=P_(SGFbM2ZQ!4uk!QG6EO=IJ#lw7x6|etS6av6DCUldGU$7I zy1j>=&d1f0* zfxxs2i`m4FdH-SWN*WrFzrqYEO@s#L7`PgOGO!lG)DqWe#BL~o1Il?9|#xt91N9_I>Lo_1s2|M4grP;eVHn=)+0vCJU#C5 zaeK;4o=Vxp*NC5R0yF@xljs=@&H=;`$tREaz2+bS69?Kl4*~UGZ`%TL-TOo*ry8I{)IJ3(OEfEb$#c^4C(69=eEF_9_ws)$uAUGKc}j>AFkk&%khpgo2t7iJOPzhNUJq9n&dro(a2E`B@c zR7m8yI;-gvIu#Pf`CCZT5p0u4rv-T&glGwE@NWl3&%;Hf)5L^-b3aV5bUhzqqWI1I z4EEGqd>sfVJlwP{IJU=_R@QLNt(pL0gPO!C>{)rt*Kn{x3#rlhPNk1 zK$_g8#8%M@Gt=%Ue0YYfk(@)gcwr_@jE{*?_rqxvFU~NqW&jfhcNmO841udR7+sQ% zwF+x83MJ-*aEMdR!H8kvgpcW|?ld;S-AB?+^v)u*1%(8`kZg8nF~UZB02dfM?+6D^ z11TTMPkC|A+fRLP55Xj62;D45gb#v;DJOPcF~WxyjHqFt;L4&mYbFT8m>w&%3c&P~ zQF;B12+@|H)KgwdAwD!fkm<$rG)+`+YcRse0$l!%BX_2Epr^;&rXNBAvInzup5!H? zAO(FRj6nrs#LtwP(_x{QH0AE}3MNhdoOglltS_*B75T~!!3kYNlWq$bwimPZGvF)7 znWln9c@4#Bsa`7@WKdmgAz^^5s%Z|8>=g6Yi%X%Y)QKk;~Y?W2rGmXTZ=I;eT19^Z%uTSFy@e2P4q=b z!l1bk)r_HSi@kNF-~fe4?+h4O1%>Ycc$1d7J_OoFp?aPXEX=unB7gROOY;l zVDLvfLhB?hyX83Vg3U*vL^{!0gjG|eeCP0d!jW?lbh=j1sX(ETwt}*x%g<%Ew)r!h zYXQyDI!rT0hrxWC`5%3522#$8r}oe+efK6q(5Z{Vb0sh@6^KJFn*>jVmgJ9sTqrk$$UL{AjHsi%(RpbjJ>bYl}3k| zyAB~iUep)yU~r@Z1LAI|sAn-UPkqFW8@AJ;6%Z#gM$+z4T*?6>WNL-;4B(4RSi*tF zfu!EUxs^0KH!mT&W9HjGFyyd&#ZHBgCbpF}x0!NM_T4P@?)u7XaAhQYuwUc}gJ#rT zv^Vl+6wbTb81<_>$s0HPtFE)42l&8zU7s3eQyv&GYZ0VP9NtL>+K^6FbOq>QgaK-z z6X7TWX>}<+g96f|uECD9pbhlkI(T4L8b}C+q7M30Kc-^{5zd$Z)HC=(C&Fk1ka{&h z_|A8}lm5^D?SGT5+_;<`JX}g+6XR~#;By3o2atO}gKtX!j|}6@-vrq`SPdV0&kK%hy$`t!U&d z=Fj0Pm{zpjH4UbjLckG+ z-C(3^{A4qa4-gj4$dnCb0S_;w*XziIsjowT2R8As5e$IoQLGhk0-YU2q!;DEKXw;^ z3v|pv#DfNzoDTR74afJlIV49o7(4=kdS}NMxH{dU3`!=-q(9a-vXB5<+fn_BC+$#% z&)72E#Ngp;Uw=DYy>c<_N^lZ`9aW@%6exB6JsFU1hDV;;F|an!VRX~#X~H2j9xptz zLZTctKevs43Mw^Alg=B9#kkQ451;)`CojD>8t+nR;@-^Uv=8&pC{q^SW#A3SPr-y4 z=^!8i3$}pr9y@SYAm*SHiK)L zn4eP~q}gRAzP-Jf78e&Bmz_UTljEL3fHR<}aI-7tFob}F1B^`UU+I{JjFyd;Gy;SQ z%vDTRF+C5@-h3|TLnwIRS~zgMMm}#)>1CRwSXa=yr)2a@zTgah9xr$cEQPZv9FK!eiO?>7#v{XV&&R?ksFc$?n(ko&jd`EQ6yZ+-gfH8AQs0UE z4_%5d{uRK06^5xMn4}pWyO!ieGK^MXs-80!bAwqkO6GF8y}g*T=g`^Y=$JeA8lMwg zTvR$ezEb1bm8>M-h<+7WpaK9iY|HB)80M%jw8$encJ9EI}JA9VIKiV& zVy8qnY5a1yQ{{OID&=&KrXL9$mw!84TKgV_X8E@h66(6vA{d!+GCA*B^0bZ^2h5%h z%ZL&t$*vtP$CIa+0E~~WeBinLv2pHl>hs(;+CyCV&@E=T=5J8LJckDd)aeJseGby9 zga!-3%5GC{Apq^G@~I5i@tzrCxWlkWm}i&;(>Qs=pVNeR3}Q`3g@G|*$2yc;HEM?O zlRlb89>sHFdVOPE!fenCI%^G1Q~1F^*%AxCg3(yZkxgypdf46xhU}eFgar?oJavZP z+mo;%JjNwd-EzLeQ()HGB>Ej+0|PSCKT}`SKkr;;LU}#1SGtrR!NPPR=UtdOLon~| z?D|^}(3W;VLLpRXL(l^Xunr%>LC%KZK{0v>0)!?w(+*g>qMh!FMhLjU;gK{oGo3D6 zypS$my5jai_+EvBMv-#-o)*dip&6VDi6;X+zxxM&_*hR|w}N)@%iiU%8Nar03M%FF zj^^`dz8QFKYl^TZ0m7GUptX?D=v7Y)e8mIYse^fN{RVUFOmB3XDR`8sNL&Zb`30XV z80br@OG{~KVbME&rYEP;^=mi0K+A=HzUXgb!v+Qeb0iIHGzC6d1Ho{PH9_71L3TRI86kE!YU8q zMtty)uPiS5! z84)HW?o`U}gsUkJ+5?Nwm_d#5(GVBZ21svoe9Ym|7)g)mE|<5SH^M{txlV!(PD^Q; zw!N{)j>f^l{M7V}aiqQUissXLzk2;r;!;2k+o3t>-*|TdJ_@aUk3zFFvyebvfGK64utST0p<;^#s1r*dsFTAr z>8zY^g~`K^ShQxB(8k89!qhyvXYT&`wJYiRE3b%Qk9yvHds`!1^<3tpIWI9Jo6$cb zMQ(8=Eq`M`c(QfV=OBs^xRilHU@$ciH@FHZg^dv@^ZP8E6OZ+V@v$*8b88yXDi9Db zAA}zzXBx!UT$oX*)cO~jl23GC@ADU9jnQ{7W5~xe6$im!ir`HQP+?@vp|LzIgmyqY zrglis8km`2Y|#wyBIYQXGO9OI*AH{;+(QI?(H>%97yJ}a2B8+Gii1Xs;1O6Xkb8t4 zMbLXJ{6Z@<1J($b&Oun%T?Tgq93_WI!^9~gBmNKoA!MLigo&_}8|EG97h8!%4+~V$ z$J0sDAgXLaP`mIpT?y&f#Z#9o6^eas%dlmrI)2$3`$6-9BR3p2#Io^Y4+?!(gAcB{Sc3*1VuA@?C{J9iL!la zI0cn5E=O@XOrV*6EBs-V8O-Yyw6(3qeZ=Np49SoD+NosI89BAeNLb<2Ilb17gx*^y}*uB)-dtHG<(`sTj4iI6t4Zx0ov)O=BZtVzOPSx)~!% zrU=**&$@x9i`2somh}Y0E{Z1QE3k2oRb(=9x`0fnb;j4;cRe*I+Y!B6kD= zBi}4EV8-HQ$}^a{8C$JjvdWw?ASlfI5CX~$0RbcD877)X+@vX@DsJrPs)+tfn{|ts zGPOls93n$d5XK{D;lK%G-eI&cx{pJ8l->Sy_h8(t5wI3y#w;K_?k=JecZTtBaKf^C{?sz(x)CVX9LQb`(fj= ze*An^pjtbDjLXvk>h4KE*Zs|QyK7GlW_B%rhTRF!;4|dsvRh1X91m3D(eUAxO=s90 zmLHpr-)MWSpox37%aGB8nE|Xna2k1gi$hB4ltPwgP9pb;nQyEtr;k4Pz&nQ~CdPbQ zDrMT+-BFihp;b&>%t1Xp?rKu+XVDmj#y14++_{tXw%Jp^DF&iALMmU(r)0d%l=TLG zQB6ElB{7mP*_zUTS+UlE4ipFn^YWM4n4%KyJ`JvPai^|a7kbZ3tfw-lgvF?xM)=2~ zd(6Y*&KBBmk5RM6&BkpXBFZ0n*`2fngb$lhIt*X$FzS6Vz}>t`CG47u7NMZtX&4;F)hdIQ_nXR6WpWU494$805Azk6rNY3eAf%7Wi!| zjs-!HPS8WlStz4TWZW}ke=}z@>9|-g_a|^BPE`VpGV)yuv=itN>k=WD4m9$oJm5xH zxk#ueO?FgCxI)8xod^P!bRE}6sSv`nQv^8e4_xAm2Ko5hi{dj_S<~R-rB`20d&2P> z-}+|yC%^l{o#}!Y_p0_aC?YsQNXUq}^$Ek;-i|-^kG8-S8KWBA!#w9^@1=@Hd)%_h z`2rXoBV#_y4-OK zryt4!1BQ_>?G-{I1QWA4nbxMO-aS3y(LJ;-1Vv%{d<7arMOuz<#^2@FNH|ZaVKYKS zxcPIS5J?Oe8=PT=jdg3)K|pwb6Ve820WvUDOf@dN6YmRer2{kPP~El!CkxlOArKgW z=R;^;&K6Fm^8Tiubsls1E(w=?U9xp=PF-e&u$Xq1_wiY5?^Oph?^4g%tOj-X*S z0P(Vr$O0q#k>|FA715zFi$yrEQC{o^-?!)HD{wCXgGi||5_%rR6%UkJ_ zrluGpmBE9qNZ>9g!fBk<+mv3H2fla%r6Q;Gm zty+!qCdh_e<-zW_b0Kj&w2S|wghbCjEloFd3hhYPDUsVlYa%quAGf+G+|CN^+V@Gy zPes8vKqhMuE|(JL+6qsjz|3Vcb;7g|+Q90{lC_7tdno3;*$*$K4l~ebai8e}h27j( zOUsK3X<=c(3z@!VLwRyn6PMxn9K+Cn(u(x#>ICO zytV*MW%B5rGO*T=*BkQMLhNP|!;#_Sb6$HeIb}mN1$FqSBm@I)q{%z^#7K9aGzm+( zJlNMMK~Uqvd%3=I_&o_C$taZ}M(IqWI7>Z8Xh!D6e1B0U3mX}Pfl`%!)ER;gx|0{v zMmrMdj6z7u=P96%(l?6w0ar6_@>3k+R5zi8G0F#T!aAJXc?V2qF?839m@qi?(e-PzKRUX+t+QG(t_|9S5 zn9i_^^0%VFNgEj*DbS4a__Db|lVFOe>tHtxa1Mbf0%;cO(gK#3=Dn?SVsy;$IRC)+ z9k_>SVszBZ115`bU_F8bZt#Jbz%@7sH!(h{%nF9W=vvH;Q92q4(?v}Epk*+kC$10k zfv89HoMvXtgoWK80vb%vJ4TEwR0s35w*iKS&|%(tPjQ*fu)7R#(I80QSBxkf7%2Ec z6Wr`ygym`q@M1)Y4Ygt5;Eg{_3=nGyyv*Q(xiLM%C|GF7KNe(TI*BQw&^UHwZ*KCf z?hQQ$ofv5|I_FxA%E*{U#CffO5k1#kaJk)xjoFpR|RgZ51ubS86Kx z<5R{}y{U-*~P@P5$7BT&!I5( z%&U+3lrx$G(?^t_D>;09HndQK0t*BJYYo2KP41yV1at88j{xyXd>SF6Qh;X|j(65n zU`QOWQyOSGjMOD`JVIAmj7sGo2E()mTsjh=Hl2mDQ7)04yrD=@*9vP)WyfN*aCdsd zfMF6Y$|9t~zetDla(ILlnwbeG%lmco==epLKH*P!m=5A3GJalEC!ErQ9=&p7st)an zG{KIYU0i<-t@&D>x8yP>Cor85WHQEwczEd9smk9%L-?>Qm#xlReGvkRDJ%qZq!V8Y zgweAGQM2aYwGV}5gin32BZ=K(2nou9=7UhHO6ct)B$OA^YX}CO5ezYCh!0BDwHW?n z^Uiq^%EZNsoW%eZmlqvpR|0_ge*KL%(#(a6q9ONhvCdKRmS@rcPq#TD`sdjMX!|Tf z(aIk?oC^sWXEue~S>f@OE>eOq0KpQu!IXtZuIk=O1L|OGCEeN#rq52K@!{dLvA&jW z-@cvZ=jZ%Q>dTiei+OdYWp!Fl*J$KTr)E(a#=?#jzHiOlN~}qEE33l6FUK7e6fygGE?!LOfSp?Gje!-D@nUq!-^a|3+Fv)^ff0aH6Z1jnC*O{`V0%S!dFtijRK zY{oBeGv;U#AcnUw6v@o+V^kl962lM14)aGy5p*0|M7~NY7WWhSz z!IwG(NQb)Q-I|2dHD5BR^f-mj;DT+gtZ{j(tniQ*=IHfJ}T#?NaJ#so$M zjsVO<&;DKlqrbgfk0@CqfXVnf5{kFAv6^P@-AgOdB-na-r*PBM-~5+Wia?pz*k4J{aIl!p;BTZ3aRpEDn51_)iglfj|J0SOJR^-4bR^ZQF`FV_b1Sj1}c0fJOnCun9ic- zDw`h^hl>QqBn+merqkf?kZP?ft!VHvIWcK%VqmCZ!N9g!%EESC(^=R*%aGgTvkK8G z&ko0x?*$SPbPxed;23C@KW=qXxSbU`i4WsDOrfx0Wa^-~6VjPS)#(`ZudXcn8`i8P ztSl|3m6fG*_s*^K@Zo(klho2Ab<1sDh+Cj^}A?Tawgbjnpf&rUwWkErh;AT+{fH`Xfh0|d~E~es3?IbAnVN?o^ zfn7ldhn3-((P@#p{}HN;t?OU;8$=O9>&ro0GT(#pHKFxF16DUb4J^zUmuBrsT%<|9C6#=?nkjQkNMl#Mlp zoh`JEVy#5l02xqz1R85IoVw4NA-LhczaKlL2*Wh#q_l^zv2jl&aSD4!0+4!U@t*Q? zZh~_fY!9ZbQ2$JMp$U6>OQ}Aq;P(6sL#Na`u6&Pu;hM%*1~Y@gv;(!rI^<-^$}P~)>{qD{2R;G2+hKl{MDxt4s4~{=uCzGTfhDe)(m8XLxvM$a&V(;n(<>4%;==S!-fa;wWYSjBa5l z2%LU1Amv5Y4RnMygcFv*%o^#V@bMgr)MfxMNNl-VOA^4FbDRi+o}hOz#wt9VH~GhP z=(1IQXaHW$9|jDL%+t%AExynN=59@>a3_o&^e-le8}Y@kJX*D|pd`%IQ!v8oO$_gV za!8jV?~G@z51*M34w&!{cj(FW=_?N(n#M83!@@C(*J8AN{Te+FJDVK|n$`7ch+>grB;b}%|J|;ZUi4GVS3`VRQz z?&2L|%42%Ul;c}`BjEKR@{4HIYeQ{^oG)A>&iVtBheY z|8|hW9*1YEv|`6$j&Dm44~*zBY*FRRz|Pi&zYD<>2493DLUm^|jgAbYOBXMsiHQk! zI`ZRt4y&sxUd)DTxN{fNPLWaM!A>RQ56s!JT5;Kj0|Uo6t<1Pe<*1jbVCuZu4UGXN ziW?QHcRcIii+B4gCm0!;1VRHp7FZc&#&%iWX&e#XY3Lu!<1}-;ck7wAfWSA3m~G@i zA-Z-l?VVv8|UWoM8A|$-#Bq)EOEG z_2V@Uu&2m@j2SVXX!RHF7_mE@D0@zyYqz;7BY%^cH3rfnZE#^>+x1I%z*{)dCb?P! z9Kg+jPWcm`HHpp54G9L7qnOUJHY9+C2n>X=^N_ZQX6iPsI=6r;@Z&rM2M@`Q!3P@I z?jF0lwj_`?($w^HdgHCPBrGndp5q!7+C5<5rZkJ!b2tM$De67Z>89vdVNL>SSG1El zl%Ik2k{EyTYH!pXj@a>B@;7rhv`=Ep=!625g(*L~0_9(RFPlgMW~E5bi&u3}Aculs z3`#9$k#JjrVr6l`(@t!4?Gy7F9U4e8(-U6MW-gn1nCQgZ0*X-Ko+j=SV${p7nD{!J zgo2rJx6%j!;SwwV#*#-T_LJ*0*K0f<+Gg^~7bXb9;5njUi+RYMQD)e|h+V=i7Dgp8ab-^e4IaELUqnUe86 zQL=rO0;4j7K<9wijRihxm`o`-9l_Q%AD3FU#=>YG zdU?uGNqZWpz}a6hbh%VM`GYspX%TpeXTl4rhQ|pN|_<*L03BokC8dS$Zc)J~~7|<8%4_S%tC?YkWS5v4ALm_YB#e z=?=)qJUGC1Rx|{z_GXmF2-WGRQ+uSUa4e=)w>BNVDnSt=On5VlFv2oY9qX_R&sT3FbG%QmC#-d>I7ZHFcijGZ-u z0Z-#_)9Uc}cp4j@@GYxjlT)7J;c9m1yjzv9me!}2G&I1Dw81nYyI;lN>%oeB3$YiL2;;s#EksYDrZM}y?+g|s22j^g}>+J+2iAym*1 z@?k;9j){EsTttNoUsA4hZyzdh+$k7;mpFZr+zBZ>XK6RL{_j%OE+>hlcg_Z@epEI^-Q~-i)Bk0Kq^$zpP=I_UCX`pv^o9c&wU4hH`rG z?8mm?&P@v~;OKMdA(P;7P`8ViV?sC=)C!YIx|^y zJTFdaRLAI$vk+XZfZ!o4BTX|7fk%aKlEO9)ybH?s9Iex%&zKMrhwm7*u=;b>AYcj! z%_3_TO2><<8l{6%n3!*8ja# z$BsHac69spmtOSFxDzh7#dCP}pwt{X2P*qGXyMfqigs_vo#1(bGR|kgzgc{CCc!A6 zGaWN`bUGXw0t|p@1Q`6r+Io6$@2;Nr(#+JfJ1x@%naOdTMZ9Ztr?i71}I3OhWmiXw{uo!VHFk=W0bB-?u2ChIb=3Uo$wqfQW zSYvTK3k~Ar@CXPFykXbS8dNaa02f2DIL(?!Y;T3Se94O76 zINnJcoWKP)?gZoWsoWWsfwbHPqgdzg41%i$X3(i!e=Zu*61cG=uoPjhp#5&|n}pua~W&M7gSekHJ%cBCx?)7VS%^YiKUtvePPocM)7 zs6Q5+k~w5FlbB0}!3Lu&kE~^cOxdJ_CKJpf8w5+RYwBL%iu#9d)cDj6P#uTq#3W&YF#GA5$#n7JjI@d|F<%LG z=J^XIIW7S)%>7oX%Y)q=PaX2@kfFgo`3)t$F37qC*Q;YZ0>0EifytbZ} zR##-!^t_r@H#XBcSE}zYIN41rtLqxLY-!-KAuV<-ZLDu8N97|8mpu5E#f1wOOrNYd zuqaM@Jcnl&x@I@I+&H=g9S56tMsj64yJwq`SlNzh=IMAS`s1;ntlC0j8pMf?9HtfI zQCM@Ji-dg=$a$6X%onSj6{52%oiZJZ^9tSO@VlwMcRwx8-c7Ylb=dj)skXhDUb=oc zZTlO{{Z{E$mR8LqE?>B)&e)Zf7M9g{*Tis`lG!)YWVFdVv3JujnpWBa%3EVV=Vwi# zVEWmHQJ0zOp-@q|Wp_(x!7Rh=&^?d(nL1KR!F+IcN(50n7#?or_`)=UDI!MY7U~^0 zVx(w7VtRam&u$VXatJ>$%^sM$Y;kOlk`WLr541Qm!KLK|pL5~jz;qyONGS8Y3H-1*jJCZ~ zOB-UuLxZDfmpu2nWs4FDtE5v^gMuoWK$nD*1UVX;r{_{{+O6&v7Yr(l(ql@D>&`bN zOc217oU(1J+^MTC)kHJgE&SPL3%;`H7YsgFj7A`szFu!3Oq9EqdPK8QXuqqz2Zu-f z&Fk^$nKV2)k}A@U{T_Z!~wJTyKm{JBgqwBc4g6uP$p=-UZ+EYJan>`xUs zE&p-!RaF)b$JhuCpzKa!$Ay2=P^LqNG&wUgtBfNf=Q9EV!ggT{VhY(k4mrgIYCF|U z&u7m}kEgMbfiyie;qOAwkr}zN+Xkk-w#KM#)g!!MbeV3M83&_>5kwh+DIS7)4hXGbi5A^^{2_n$#nVZrF8xJ)pY5?l+A@1)+EN|HlT?#aUd)*B~3Jolhh?)g2}i4s@_U3=o?>=cP-I$wOJ<0; z)x;z*o{o|qn+?WC$I|rlw5MX2in@H|V!CqWvd!ho7t_T{Gj``5D9%?fSg?^6=ugZJ z_e+rQ$ygS-2UViOujaw9c_u&F0L+>x$Y>9=cyJC40ldHw$TTD#ahS65G?o1Ev(Qsr zP)6br2LC-YE4krE7|L!VoM^Wk^yE{oK3^gC{7F~BoWrvTM}$N+85*BY>USK_H(Qx@ zkUMv?@Y$~w5axJubWZy?lcDh$!x$?+pT*<_T1+$lVE(~)n5PHm#CPxB^;XxI`{v4o zT?+<(b9jSok=%_F3z)gnW@d|DHjLt1L5_1=eV1{~P!8YBl+(=Nvo?|6^Rrs3tvoT9 z-OKMjFM+d$_KnkjUSMv3GOphJB^#XTYaF5rc7E4S-5r|ccVpqfb>!hNb-#d2XP7E= zgiZbB_)Og({9&e(Q{#oekd`4~asAqrG$S|GCeRxA)TfjPG1>!PE{L#TSJX%$C@AZ$ zgar98jWaSZELj(8P#Ew4*Gzw){EUANTgDUr+63U&f{QTH}DU3EI?`COy4sv#4GKhJL zu3?mPVfdgABQ|!2urTdUkV+Wf#!eWnY=99k>O-r5K~O(=8zUn-e{)*4zX<{PN{pi& zkX9>mQpjN&<7i-BKzo5zPNSJ=giJ#(ev8(55!`;+mToBSC_D%eHNrD)7!HB?Q>u)( zWq8hh0%IagPL4~{m`+oA z9v)$Pt(b8V9;`*|?Wi5bnoM60Q%}QbsDDWK^eKICIb_(h0ZeWa7=%;*K*i^0n8HL; zikpU|Z75yd(Uz<^6$UqDSoh0i3i?A&gpk6iBJ*_H(7<3C>>o(m8)}=p_H-Uv z+c`Xw(DTp!#UK7*v(DA{e3CHqiB`~#sh86`DdZ0Jc;IyDl=DT4PzmDY3_xs`rFbrb z`-dy8|vPkf_NZwxGOC<8}Vh=nWWq!AdDGCqS2zF!ea2pE$Tcc z3_>KMcOmD|d)-d}y_q5*qG=W3(cxg}PSXtA0UUSa>c zT)zM|?{Q#`8*#ZleZYg3LA6N^&7s{4jl`W%Y=mKbY3jmE8lRjnT}We3w5hk3V<6}G z#GrZgo*14qdQTdTqp$iQl@!K|sIVKK8_lEPo;)1aNr6^=Cj~mrNex1w{G8!YN}bFE zC@~wQTQZ?dbf>LqT)zP@hs~D4oh?R^QNb)wV>Z{;y&X2bOB@0M;gD%W*lYm8m{GI= z;+N@6{4&!hGmi{8PGj8se8dmCVF8>GW`2&5b`e&P%aC!%ZpT56mjQhtb|%HU(_=)- z=vj9C(nD%UZoGSuTJPB$x*e8f?pyfSWjhr#FausOtAa+$8dfI}C42o=Ta zRz3FYi|JOrV(dJHifNAY%nIi3iPPuH^Ex$J!%8qG8 zUm!D87;UB(wza!L_(y!@#gJZtf~g&ZJi?0aeQ;J{v=9^%W5XJy_h|&*lPVGv+#U<# z-4ruMP#`oa#DR%xgul02l|P!to)2d3`h3Gq;`=1vo;8SEh77#pp7Ep%Fn`RUpx}Ge zQd`u+cv?ZJzz9jp>BT>>)yeuj z%H(Xs!~1v5IQnFU2m90ATeqxLY^<+))XJ&e(a{liR!>_fZI}pa5x#v?Hq3`9ov3S# zew|SWhZx2B$$o%uj@3)ty+qyPMtE?Im|37jnnio*>8;b2aM4bRfPyGLqe|SM(Z14( z=??sqk^@DW#i$!6`SZaZuHoJl)AK%iCqaV553Rt{IS3HaGc^m^77!&6u-(;og^7EK z3LJ#9r^^a=+<1;MiXIk7@t&Eg&%Nj`J|NVq`q}m+cT5j?s>t|7d2>G@Ufh2K1tJ}V zFb%zCBGinR!hk9tKeE;$voOExn`RLN+?nL9uWL*_9;AW(0m)L*K!eb)^5ir-(>%^k z<&5%0+8AgErTld~G4iR&2|x2CLq3zcwYlMEhmoN68k*8(r_?4F6l$;wxd^Vdjj6%L6ILEz&*-fM@zG=_^8Cews8jEY7MUHg0zwJMyesaD-g+r_uh_aso69%Jyp zols~PS+mK8a+J%G%fV&|+8SlfcTuqg8;v5judGFQaH6=hN2ZzBX~!^;3QC>Zy@xo$ea70d(-(iF1cn z*RMaj7K!=@Yu_9_|Eke9-UjWLX%Kh@;A;ZLcP3bBQi&ON))qf zdXmyq+@O!jrDvEfxXRIj0H%&$Kzro7AqWZt$6$Z21q3$%j|>rp4^pv7LG5#ISEK&b zw8`jyTcdy42wI6CG?#s~rPwaZmQ(}@_`3ZRhIe)+`TnI5X{o~_%4gVu3yl0d5~r{D=RDM;q0uZ((c~Aot76DEkro;k<&PbXAe$QGezGv z4UDK0$T(&jFe4M-*65$z%6=J$mzh0&nYrp$%==L-!i-2Z%sk)b3SAI_&??SJAZTS% zPH75m=DZhi%V{~io+M@F<=&J`~6Osav8Hh^T1Fy zt$?sDSFxQs@awgpu)DyE%o3tt##U9fuCjw|P@2V{?4GVY36hkCB_uehJvqUYUk|Io#2(;htdLV)6)1GyGE6Y|8Fl=oSqy*)JOei9bAq zrXU+Z)Mz_Q$vk#`PG;u@AlZ)#)GgH=IxOL2KmKhsg&sgJV?G6-HJ>U8n|0$~92CO>FjKgm5b;N4WC zqe_2lByDbTfgfjcnBwHBmo>G+O$#3c1p)?}){A0rl)lMf$E1NE7`8Sy(+BUpmuk{- zK#BHy4$mf>N=TF$1JL+PN7+vr#0nt%Fmq|1i+q52HXO=>lz9`CuCiMjz=ft z9g{mcLLdWSydEKj!ZZGa!y~LSkdj96(k!^nV{niU9z{Cr zLgG%RtTh0XmFG<7GTu3F1}4NIOm+i5+*vQ%;Pbem1!-mNgLH_4KZ6^-r@=N^rc7Cv zn4f*<^w3yN#f+W+l*@Y-^R%HEPLIR*FkO*HTPXL_a;MGDR__aF=HDq~q@M^VS2YN$mtXzaX*4(dHFM7(MnnQkkx)!|c+pZ1j3&FqEZNP(_o{2#8&dBN(%SM;s;E;E z&P+?4l!CA|abzgIC%_>mIw4aN?)*xcuyGhG()Ny_&|T^VQri@ZyYY@4-I-$Z&h8$* zMu(sS_sn4OE-3H(ksXKWNF?0-Y><7huhK`J3`5By+EWgPUm@IxLgp9&n0sVSSsW|; zupat1$yh8)>ZFTxXX=r4$j^EP)>a{Z{>hmc_mkV@@?p$01ZTAkFq9@x zqeF`DX81$Q4flDvX?wTo1`y0ec+lBoU=Ylg$9I`4;%|KDMoa{DtSrdJCey(UK^gdJ z&SpURkw+sCg9Tg|FRa=&%nJsA@WV}v7&kZ8QiBbKiBp8l?a{lOaF?CS1Ykq=nC2o-`V;Cm&cQBnE4tycLX0QM{- zLR-og2eM%T8~kW@3`S@}HQ_{i+*Z5XV*LZ*FQL+>0m={?E`)!N;%u+3r{&q%^!-2m z)3k8=E^10a8@0wLep|a4r%LGdh;)6MVXYdgP}-OU)mGvnK6ixt4M zn%ImaDQAG(psjIH$}*I^SM=H6-4PqzOM@CQR<}0AEI1<|A)zqdxl*fo#5OiQCT(KK z<>~2`P#GLn`aQx|WtDLrq>r0IG3xE@;-qnCBF0u+nrk4u0|-W|!ctcKE1v2_e*P}C zS|#+`Ba93O{=EAK&B6X+V=!0zl`rvWJ5I~##Aw**%fJ^I*am%}f$)Lhi(7jXZG8Hi zuG1E_P76%{1`2+ZfN2}yNFB*TVU)YeBVY2BF_XtA1k-x<6l8xuIh$G_rWzoiZQ@Zk zq#fxKPq@htHR6l@!W~VID^pxB;uF?oBMGIZwDXok&LZ3Zr z7-WXcc?Ot#><*%igsakI6wh8Mad_pk?`^TY;3N9%vLjCEgC}<>!QlCR`sU__l8yGp z*^`}ZuKlj2{TfJiNi!XhozjklAVNbe2b`2HyP0+ou6-3{&PR%BX@hk$35rTzzZbl* z`L@RR@M!8)yxPWQN?SW=@!lO@PI&3YHE#NokfMH7r?hS56`yt0fRwucm6xb#yZpyL zH9_J1S8z>HHQx0{nC#xn?r{*c5$Z+p8turJA(q}Bv1v;RCYt8=Mw_eMX&g3Cbn}G9Pb}iJ)dLjoQ^xSAbw5S zuui#Pi}YB%$b(WcVUZ%*qpHU?%yGQqL}IP_#@;zp`aMW^3bUrCD(A4))M zsdD*H&1PCzUQ)+phf7?IFfufjhNN-Oxw+d(%}Asp7fJxG1;bW+8cB~oSQ8^&FCden z8yWHBL|lrafPmQ*0qpNiTYsh;#XIH4 zF8rt$EO&MUBRJxqAN?d~`(RkFB_z7KiA|E9;^~#dMcL(7$d17Z@Q=u9sYP z+4+eV9O`fQ zA3k>mO1K4(4TU@ea1QtAaE0?3AV-a67SOC*Ww#^GpjD#ZSpY_@M2a-{b)r#ObRfMR zNK?RGUtN-rm`$U@gWh?vva*yO&OP)T?~t?x?#>w-n@FQ$At*TY>IO$caoW%;Yewji6 zH&0U)VV#Zzk3tk~av_HLcWh&jcI+ezUgr5|UyAL1uTi}xt5<`On7E--xw`f|sO0&0LECR>W4-_z8v(BjaG6eX7I*jWSuh-dtNv>ubyD>ZJ>5 zVr(=$xPLz_Ei6hP4C;Nt0%D94u@V*)=8IucG%^w{m{k~R8T=7Kc zs+52zDvO0I5`%y0NB^)k7&Pz9jpxx+9ptW9@u+f=w$nE)%ti#@Kpx-_{lMA)j#xn~ z8Rh42Bulu+7r>YI9Mb-UrePdZZpaGLjvY+}!>!_2re2B{L0BRy$)tWWK9AZ_jP zo$d`Ys>>HIde;`8Uacwl35A!OP<~;k300+SG;F46qRh0vq83ZG1p#z8@_uOhStirB znTg$Dhd4Z9giBNR!T`YlI_ziI5E&B-iCS{d(PfVZ5_89~* z05UafoBNXBF zZX78;WsPUtW13LzjuB5VD!(f_bKS8nK^b892o3c>WlAVdRTa}r&=DaAFtx)1F?TN^ zBxoxLKj!aA*Xe;1`N*9SBqMSdziBQU5C)Zg2?Pm#-~S{5&yG0UU1#7AJ&cDERl;7x z7UKt3@*%BAj#`rdP7*poSHCKoaNF6Eps1$F;r?`aYBat3=FRlhD_7FhX=w@-4N4By zQ-9i#X2Bg~2Webwc71Iv?Mqv}I5V9_CMLZ$f^g{XmzG7I!b@42%uu7p!T~K359o^t z|3;JR|5#I`d%U3rg+nW&pH`-Mx)^8(e$iHPIm*wijQa_7Prr8Mgo(BnhVntPm{wD} zz$UKyhaMa*{CUWB&;PBMZlY_sLnyOGCV2R!aEf%Sf64txKsjIF5j;A`o~Z8AC1^~) z5gzfcGqckJqu^*HW+m=;nMsCvNPWRf#0=E|*H%~3+R~CnZo6qiTE)G4_rx2xPI@Sf zPmHIjsS9axd@}W`3evOQ1Yr6do}!BCTh=`Ox`Qt3`FU%#B*e*I>;dT}gWoE%R5J$q?vpgTwBw~eMls)G65u(@<^OV0xN4~C4+k_MS(fH!#UDCxiI;5(!WRwQ$ z7|g+2*s#?}X~6Q0y5faU3|eM)+j2)3#A$T}ReGc!@gfv)D-|(&c`!BQ9aEG|X(1f= zFcBfC8sqMS7^O!!gErw7hO$wYgrz7drga0%&KAgVx#?AEZ*IrB4FHNOO z(_?9{w<}GI3`&EjNT}2#YxdIe!eZLq+7>RVC*j4`ZiL3zrOQgIFKt&M-~Sh}aIM5bu~q02mHgR&cDY>ZD`UPwbjqh1K*;1r#lJ?=`y2E0iZxe#-)(TNaJ!837_F*6K& z@*PJ+v|YSs|Mi|x5KOay?suDGO!DYMO-{6PbP_rs<4@cE|z}k0=OuR9vy}< zbI1)Ec(>8;VCq#HsaAK~HYybf0O3XiFdrTfV;+kS1`YHNs$7&m@(J3;w39U+@-btf zj^nT#YZV953RpKo224$irq^G6DZTmH%``I5C#_-FgB&g>RD>XHeRv66S&Wm*gU%5+ru@Z=YKu>nt;$Q_{qWcNlJ zDD$>cLz~Fd$+1BH%a7D!5jg76kFDbia=fx}TUFU@D?Y-(!Up3wr95OP0^!Q;J^%Fg zq)Eu%9ZsPzfazL577*@y^2wdJ9L7+%9|vXRGaO|IhwjaQu;sXb@h(g`{buH9UXMbI zJ`dAt6~3G zM&zbs=H%TwU{d(!5pfut3R?Ib+?|8MhfSbxCr!E6TM)P?4>2D?=6K~afDj^zLp_1B z?HU!=;D&+LjGjYSkdDi3{FIo>TC{iYkzv=5%c7oQ9H|4xLkO_L2<8n9xLlEKstDg+ z)kU`$?ry50&4G$=0F+Y1cN$7hezXb%8*$ydASRJ&ojdoM!$81)2_VxIYSllFzCb{jLNAS8vSC%`2bX^zCncJ-znIjr8*Mt3Kq% zrG&i_#+w_PX=`&^ibQu>T3%0U%WG+KZOPxi-jF*77km4LQ~&Tt8lSnM{8V0*iw#@| zAQ(Q=VFMC!l&`i^Ra@`Zvx6z`Lz}@Dwi%@Qi8Z<=Hs`?{=NJRMEcmHcy?gV5jBU{{ z`jx^SWAxwB(2l|1Mz5K%yDYNJ+<8C7P(LoeOg$YL6)pVTCjxiB^H3PN(9xM9Xe~!2 z(DQ%&{nDC*NkO^EE}(IWsS}_wTLI*62d&a*mwqdzZ)g)AAdj3+v*%WR<>yAjf|a+V zVW5MbgV~0g8o62tAK*vltEdxIw>Q-`cfF&D3)AQ{Y=7sma}=c_*LK$#vofGb^&s z^@LrnGsh9wtziC`%#;l*WV$0ni*`8;dMBEMCBn!|xORAV5dib#z*Fpk0>{W}k1Ho+ zSm4cz$8rCW(%P-XsrQ{Nr7Jhmu2y|zyH8$k%TG*iQ+4IE%&um#G3?B+&`Ue{V znECeiTMGdkR>))LMRGr9cZbmrUVhU9^`UUC8^4eeb)>SXjL?iT64t(G1Ny6Z_m(Ip zx2l-##`;EDSzS$QYwP|jD(wluF)%n_ErZ2y=(^|fC~avzt7|Kw%Z}P%ZyFyNv?lS= z)hjk!WzJcVovolrbw^rmjdIXVx>CQg=c8I^zLkNI)T2DMcSR2_F`T*}nsS{8TZ3WN zFh7-6!dX>S42FU>Kw%xRv&rveo2ZTs4#(L9k!>gj8J-?4h#P77=hQ&GMSL_Pr6=`= z@)eJ^X${3=Q`-Pag|TqJsd!h5Hm#fw9)jp4vgO8PBdvvZr>lV2J-;g~?t;K%W(7x9E3@2pF3qbJ`GV9IHIbw%;Iz0k-B*%4_FQ&ZDv zbYe19SZoyI^Bld(PF_xrf{ICaR|5=I9hc7A-K%%C$a}47J*O|!$c^%UKs@p93 zauS~STV}SI(XKA9q=m&LjkFii{L;KX;zH)thE$^sLIYB83Yf-2`vGJDt{N& z6tJCfHfed$gIWwPdJOs#A4W;nWn}@)3oC6sH}Xrh?Csp!H1kw zU<)1AFsRF_irY6ZoVxl3(yhDq(&FlRx_R^EG$5^_Uus0uv+7e1lo>pjLW^3CvYGug z*wDdHSj}uGMzCf!$+&&#FAkpZM7x8w_`?T^aHlq^d#9Dti;XN^V=8RF2bxU{Jest! zZ~*Va^kw7-e<84_BB5Yv`5Bv>m@o~XWZ~ZPPZ1LCRPKU?vOoZ`u*hzQKBt2+<7fun zYS{)_rO_sNLv)stnRY^<@tMWTavqJ(z_D>LRH7;e#!f?_R&y9S1cXOrM%|_{&CSmG zGp3}@?w94Ir8F`wAu)ZyothCTiQ-Qhj2O*SHG-`R2id_GRm+~-KU%wPusq1NW+OZ@ z&Q7^_2J&=WISJlL)${7IBW#4{9se9fMLGh}OmiF-M1#IQ577X*NrzAfgPX?gP8Y_< zbPQUPH5Tv}ZR_-vVgEmPq9MTin7-RU5R0ktb+z@CRS5$zd-?5Fx9i#j+5tB6>oCEX z|L^ux%zzjwHg&=FPPVRMTxf7M2a-|Q&@5Oh*pxu>t*Ocfe0o&3#Aop41!NiuG%;PU zC`*qSJ#H4t3PKK1`w>RDs*a!mZiI+8AerXM(W8>Zgk*^a6 z$2CtEZF+FRIt0{SSA2FsA#A;gV0R~7nx0I*`tH{?8m^_0p?(i+5Uj34<-xQTc=WR~ zOkt=G9i&b2)*e&@(DZA4jb2iW;TW%;_yw3LAJ;n^=?BCkrruF zOB-s}>lzeoR<|tp)w-og{9ZmM0jMkK(T$`4KNsG4B$y#<9N84Xjs*(Y3fSV;4qBzr zCixRXuDEQ<%)FUfe$E;}IgRpj**p@Ta5R)yWs^IMfG|84d_?XH<`2Y>=wwxmQa8oG zVDd1k*}1tiAr0cA*Q1ANuZ_3MW5e>oKR#82Q! zN5tjOFAESFrrUsQAY2288!`M+Si~TFFeI84HX0F->Ef8OWBg0maifVBVdNgUM$VxL zfPV-GY;j%-3Dzsv+UZ?Dr0EW+yyfm`BIYuL1J8{9LpzW_5HsX38Q*dyEcAm6l^*8S znU;!l5aRtB`7#~DR3K{?2nqy7eCQ|cJ7O(hXk^H1M}xz|8Uc&>3qQ0LF47Clg)6yL z4#j6Nm@qIwN*+u|{X}KZk2^X-0a|7)%y1t!@)JC zgW`ihzL-$>d+JFvS>M?5^waXnN?I3vyar-zlKgto#^#P_FsOF6ohqV7x6+yz8c46d zbS({6l-KTd+Syza{r4nH*zu*&Y;DJat6KvUwzD#Aw4*|8?;fP#(Q#=JtLgm@Ka!@! zZl|F%Jw1~ugM+50GPl5_9F&PNw*uNsI|#b9Hk1}aa`b_^;m>ZTH*V*J-DonDpPK=` zWh0^-LJ`$GTejPc%#Ql}rUoOc+Z$R8Mf0*vwzn^C3=hD*3vg_Ro*N#k-_^(4< zSdcIsD8CnQ^i74$m>dIb3;BeFL?-%a%%K1{WME~t94?H5_&G!QIYTple%(k!RUfdz z!3@FP_G5|~EOs=~wV$(z6>T4;PJ}@NNrIh^(^J)|l z&ZB@F!!&VTAs`}7`5Bra5L6ZzxtJ5>!)CEAG>AwGO)O`TwFWbA7^Lj{ZG^3Lgv5s4 zx8z<`Siad2D z@$kTq?Yt(zok!5Us{Fx;lk-{N1B?K3xy<-8!#3SBErY&1=4(S>u4ug+vZTHcsWAIZ zPB*KKpdoB+#pQlmqRW~zq?MI5PpPe|?YX?7EA@-^h{nTWb8okp_l|^};*3axni%X) zeG&j;1C?}nX50(YeLZ_=WSGycayEr+xGa)OV^TPTEC)1^kE`pO(u&9Z{K@BEh?dGn zg8IVci|N9ZtELfxjY&uT5s)54v@q>}dT9kprFaV9z3k>U&^e3oV1xLFrV&n3hGRid zDIKhZp2IWKO>5HX<`x&y{kezf&i%XT*1fyw&fUA|!NZ4XUhYhX#_lG!BE`@Ti2&|= zJd=2Ch=rXYhpmGOf!lHBh`(Ns*!WxND%_4SPNTss8#rh^{WBQ-*DIo2S((`Zj|zqy z2LC!HB^x;Err>qR&z^%+ha)Y$g-0>+^JBQCO0PPG7!o&Q_EjVV)VY>dmeT!u_tJ(s z*5yl=)75L&(&+e@7=f68g@j_N?wp#qIhq7{`36)NsF|Ba;dD9hP;eXlc#9*3B#b|e zIZS@HVPx*nDOh3xC=a2Jg4}3Jq$!(6Yy{1bHU{IjCB{p*g4xF|CfR1l?9M5KfYjrx zNko_s7TGY`2OES2Qzm>9oSRQ!icIk=EiR_D<(0Iik@8w`{sf`H&KWcbgh+K~%M0G% z#O=FGN1<`B4)O5eT&ijme!zh;)g2oRxE_0aV#4c00~%E$xPxvm?Vi*>G?+#t&?i)1 z6^)|#1_+lkvPg_S12d)x5i&z^r~NVggiWQm{pp$aZV8|`%*T7-N4+?=2p5kOiy{Sh^{gt$Rsp;1-i=QH3UTmd&TnmwgxB&iCqo%jGEX>kV#?TNh|kVFKD}d?Q$mLX;>q<8k@YMl|50Df z{AHTuT{j{EPXPU>{!#$1q(S}VI@}elmeyC&mv`=@FYew>_h#>>`Gxtkyu2)}aU-p- ztxH(1r=H*Wy?^nC&R;)V_k0BOTJE$*ILb|VnS2|U- zMZ%#Cv4yw4e@Hakkx(2;{ZiMq*H(RS?(+0_+Sy!@@Qd9}lT+hqa(n`8OkdLRIS!%L zn<}CgAIuuE(4eeLYklz1CuvU&b9r?mEv~F;a5N;1`I2Zjs=S%#Qi~Pd))I@hlFJ+r zeV~~shYy+^Z`whg&O0-xzRnKdr;2r%nm|!Va-ero>Z=0$lb9-Iy!Xm9Dj85lA)p6EM28~-_` z44b}qD#v-$CSgA@Ip&7V>`LJ=zJtAFXb3sZVcN1A-em>j!7_si zrbZ`^XAGW4aV3@fM_Oe&^5$BJ==5Y{Hz6HUB>UDLNXOS}pq^I-;e}~oY1#A0^9v8t z^=nt8NnA|>!$ZcyiA)B2Q+iYt^l^UDe1}&oDKyGBR@h9(7{$?qZR1!Ju<_ znAc}??h(2SO%KMeeyb-$O$2lqW!IS37gOm{f-vpSWD21ULr0sD?GfF+;*hZnQ#jUi zz{BB0YZx2DR^tRcR0c6t!uaDo%7-&0v}m*~3}5uy_5$>BT3bR}SW6oc5bJ9jwyPSc zGIht=4O@+4A)b-8M$yWrj}y=;5R7o3GLZJgK*{sM)P*!9;V>{f;9W{AXm%e)-ZbnhMs*pEu~RCQUj1Crj%Tx zGRjONa>_{vvUj_tepLTl1zr=rvB(bXihcrpr6JXJxQ+v1M}3j5gxBtYMwHuWeVav0 z2{OgqQQO;;06}no7bp4Q5lowL0bbhY16aFhVw5Q}4%Bt0>B&*0wUef$O$`o>q{+#d zG&(k=G7TvGJ*AHj?McIZgDQpa5@M?oG9#ih(@&p$aZ7nCkFH9ZonKB%%NuERWh33Y zbt^62pG~`}$5joIR@at%mzfKulvwBCERPVfHdNnOQZi-!Mz}+tM@^mH$C%EcdA=ty z{0n~<0VsJD-r=YA?DJfDaGV#_L;!b49bt*>&bcf&i8wzqaHV3~SiU4oDLGs5*KSIm>qcQ8Y?cW#U6_M{Pw zVA-+>Zd@6`wH17ctun|RMA8)cV@<&e!onenzn{jX4WK#b(F@d^zwj=oUT$RV@uD$* z;>Su_G=WMGpH8iOT|2HT=%1Mrl;oYz(gy2SR1i*HvdJHa!;jE0w{3+IJ!8#eKkZc6 z)y4XU1SRc5H0OZbj__nUXNPqg2@1|OgjVSclm&Io*&WKJwpH8KbC-nYXu5oHO4@J5 z!uQg}3u#zd5xb=-(iZmjyER%x_y`ZiCyMK-s!E?1??=Z(XSL(mg{8FL)1NjZ#MZWz zzS?t-w6QM5-ID-YU06t8e)g#a`NGnIwZus-z7$<+2nsZ?LO=ktk7J=I(hCVHn`+8~ z2Y_izrcl|Iy|}!X)C(jYMBi@OrGm?_GtWZ8F$^@CLkgZoSkx)+{2M9V?)`B9og_L& z9m z3gOR};t&j0^<5UqM_tH58xisGkLduaKvloLF!6q8 zz>U1oE+_`{@RLxccVzay%cW@2gyfygu%SB5a%)#p#*O7M^e*+`IZeMZ0V9UkmU zGgA}k;>=_kmXKh*=)%mDgv5})nm8z%kt%|5TLKe-%{m5WE6}Lc#pruwb2Z1U`w!Ed zhjY>-`qC!akjlf_#Ha+$0zt7U+B4O(wzH-IV+=C-R5u8S2@PyC0HZ-3nhcH4<@aY5a^uG|3X1I3$~2~t z-%kqVxW}0cjn8F&TcvEXmIjVYA7QhVjc*LIgC-6_Rnw3=47SE!Jlq%m`uVTua^W5A$>FdSCyL z2-U0cRaaVGS7%z=(#Uo>-MTkxv#_+0R<|_z-r?l+ftajDW-FU%abY#hFRY{mnZ?EB z!YroM)m7t>cTsI@uF0(EIWB2rRFBP+m1$9Q>OW1MWt z{_(8@<;5DCjCjA8xWr#?cN*yH_2EtEGFa(Pd;^|BMkcF#~0-+B;{Vl+v`7~0r4I@cpzFXm}b!N_U+qgc6Qcu z1TS{=5of4>z}gvWN=!GQxq)TT{0^Z&{g)Zgfce-IyY3LG1N{ho)p^f>>bob6jSQyo zv0>IEj%pHsE3ts`b4w@~StQX|1MS`)2Som!OIKr|HO8n3MoE4&Jp4-TjfPM~1Is%+iup*#G_&pAhZ%9-(4Ou2J7wUzeMNf*1-+*yk2B zGG><&ngeNg-9~icTmsCC?V(^_)99EW$gR1#MSlcmb89Ef&o8G3a}qu)8|mS~Qu^Y{ zTWMJW>A{1CX?b}qElYb@Tw3we2f`dXv_jEV`5};Cs^A@8lIv9w5sVUogc9S7)7MlV z(_K+;YY>HI;byBOvsS@?*%WqVlULaOQvh$zRo<8o#(KtvhKf_IvMo2Z>&Eocu6G%k zSu2eV30S^az3agVZHI6QUzIH(+uzrd#)pUFYl%bsX<}@|C#{DExdSR`WUtY`G%9n}InSS!#hpEcWr#`0iy3)4j$M)|L<;6yU zv2i}GRY}8o9+eh->GCC?voJsktOolCc+nWz#p??RDw}HDZGkq10|J<7x~-j!w6s2- zY6l4GssudW7m4qU^!#`KytoBcK&L1}qp&D5jz{2`5E5bPOfI8T;7w-`FrGy0K zcLFdAH4nvQ&p)3)MMy9Oz`;Bgk6CjxOCg^|BX^*gkSK@2W`-!kVf)FBghxOhzGpvc zGh!Gy9U$aDFg2%@g^39zhUrjf7BO|h71O&l7UNiJC^Q8L2d16SLYSW>X$&K7m@wxO z21P@@!!a_V(Jxn-u*M(;xv{aC*2EZj-r3zV(_a;{UtHcu_huia`w!;Q@|uLv_O4GL zfA;z3X>NW#t#enCw2P&sRU5VuE-x=iyI9o7cgw;6A;%Wkz6yeX)imbX1u7Q;fRR1h zS-~@t&m(aQvqMe5cXQz{0?>whNKp9KBMGP-!agD-BzR3%!iW~ohp9mpp=oE_CAGOF zt!#%W$+#xOp_L&5pF@L#74C83Ti63>bZAhFTYOw2(Xrv7ba7@XO;3&4ZC`C|LX3P$ z0)ib*eBg*OKnn!7HyTJ9OP2VG4KA0XHSpn~<@N3K*MIlZbkH-9`j|pG=t)(DWy>(< zg@z=AxV4r`0l5~0>B^foZ>B!hh!l>2qyFn~NSO>O9F8=M7a3GM)p)cUy<%t^+`YAF zAu*eFYU(cL4j7p z<$4GO7NC8aSImjLNtbz61Og0gKx#IOit`Al+??iRny$Nx>$>;Ss?3jwW&>L>lZ>GQ8C?gMSWhHO^ zpp<--PLJv6uue|&7Gw50jz~y+7&cdI9XO7L--da%-)rYFYIw1fh;wEDw95**jAUP%{bW-KT;jL4$?zWyjrzslStL5y}o zdsp_}Ni`^KV0E*azW>7?%ifVF?M-VE8e5_xngrVA&X%;b-OzSelVClA8wVyOU}zq3 zHpQec6xJbR-u0-@iv=oPSxBhY*pWKe+*wNxm+qyl>Z&(-)I?AE(bmRJAtdVXD3Qv- zg2a!7OlSvb4A<`caRB*;X~Z)+i|oSvIBZ&$?*wp~_;p;eE!64cyjf_}{p*kJ$krYt z0B~aW4bQ}yefS`K_Sr|$A|xa(UpDj7u+#C(5YQYLC0a=Aq%Njz#3T?DFk3Stg)8HA zXo`2!H-LAdl*9RMr~-1k2|Ln^=XfW)-IO=KYPTtbBY~Q>ppoo>m|E=2VIft*Kpl#?^6~MB^vbKRrK{Ip67!6+5HlAp_>ki` z2f&06bL(?+50k&=tn&0}sEuG?8**q5p+R6%FZuilZfFiB1V$9gv}cE!w;~G{z~z>0 z|APL9@5t^DytboCJfht7x(N46QMP?gHBoLBmkH+!2W41%2V7_5#d^`+PO7L8GtI=d z*8vFvcF%FO{n+SmdilnUG&4P!#^g`ckq%Rg)B#g&d+TgLmX=!xKu&d!OXybjyVDPU z_VcuRAU&f}u~x^L+}QAl(BAjdB5O-rx6Tw9LIO>Q+mR=yr_>F4MQe6kp{E2L>fmXn z3`cxkJW%l(g#@jkrg~rBT1^k;zLfA?7p>xwM$Qx+)YPv2$v^*tLm^Q#urlOEh-nF@ z6cWKOqA@o!8Or%agATv4d$=iHa2Xff#g{W)bTDt(^Si(oTq(kMoeXe*=|4UmMX))ivIR8)#u#(<-=iMlHQLb3K&^U|Xnb#z$ zimy?h883^DG5ThzCDRz3u<2~%#i-Wn83N-VLmq?+h9)5)#tgdPPkt6mQ4=nk-|dce z!1_qM+Ypj>!o#?8I&N34F4YI^CV>z-!X5Odqv*;Ky5 zgDWhA2irf<6e${Q7JRKih`#J7f;OC_M>D|IgNPCJ96-GXffU{3gZ}&m8H+dhGu;M# z_$U%PjjV~QL9yFqNt#ksbQ~1!l#iWS-kGI3K_)T!DehX~PvIE06=92*}`x9{Bb)Zg&%sI@rg$J&s0+KCX9 zA3~UHA{6bO!9s5P8EPJIaK@q-a6Ql9@`S+QI5mTzF z6LLc*BRn&veio_v)B5U~^P)r0F*te5-7PS4+=A%`KBl`2ohwW+b>R+ZFNeVoH{P=V z%6>q+W0F=vFWtF!-;2~t^`YUJF*B7UJXjcHF1=rjmBLy0$~~r;Bn)Ktpz)YN zg%-i#GS9L1#uXe&P-Rz|a-$6~Jc`j0wu>gWqK!iq0bxvYmEZK0q5D>)h4IQ70b5?H zRjx0IU0+b&mk-*+)g)>dio54&y#D^)G&WR87d3L{N^nj>@2agau(=>N4tb8LtlSmG zH#RoauK2jozS3rjkn2qPIr|{|5D@uZtAUZxw6Rn3!u7)?2`*JP8U}|7ITQvReW4;W zwN@>6(U^n~a1{w(HXp>-?&4~5$_I#KLEB;=0v)5h$_aW2a{Ke3=y``Ik|9crlj>E2 z#HH1RboasMdft-uK!57;bmG+144TBDkRZaD;VB6TAXg-#2vl?T4CO(?#)Jxf=ob6% zRq1MEe%Bu)gI{z4kl-+G40DYz5^rf78c5v|3~CYSU~407tsxNNt|DKNy}>sS z)+{Js3b?Zvj1ALZbQTxiWyUXL#H8ztioQmN!ylVEB8&}GkN2n%8R~?&V-=_H73kOR z*m5iKVOqq8whDiWNf&0@XwWKX>V;v^fn79wz=s7<7;G<#`T|DAjFR`nMAo;&xVEe5 z*6q9LqmMsH3(HFq4rA%!l`Fn#gZq`hX@%>;w=*5K&E!W%M^#*DE@%WADc^kcRexhV z?m((}s^j4TTX471f=0KD+|;p5FKq}gbrFyfT-d$?OMmQW${|RK!-MR~f@$|x1}reV zGfX3UdX9Hxi8-@%k}Z=LCdbpn#HbgNYZ4HA>x9uh8U@>7*QK5CU3Si^tS>KngFzQs zpUl3}W)a*MAPP@kj)*ofG;$~;7FQ)CL?@b%3Ih&Yi^KO-5UgxG;8Zuer@^ZKyD=i%h)d8A?TQNyPTSE_tb2{TLT_Dm((01>S0%?}*GBk5z)Dg^8;GaVG!CYB# zrfGr>jSCHgj+9izB1?3&n6l}evDy6rJGS#jc4wwVb$78?%>7S0W@D>tyKO~}sxC>g zn3+r!84_CDiwn8W^ZIe%1`-jGf-Gj%v;%(q96v5U|NIj!KmGJ$qMeoReebu*Bn>P` z+K^5peL99mdrVBjK;(!JtKrU8+1cJi_1{L4KFE0a)2C0fp5M--b$Oy^yzK65$6v;g zwf-;@zgI?amLaQ)&0vzvCaHGj^1YV*c?0~F>g=ptg=@$PgTR3_Rg_7IVEAFpDU2gh zt>N{n9b2o^9_gLumZx~GG@2!!#C194_V#Xh|HF^V2iT7ue432!-M?FwAUH}|4uPnN zY;JAR4xXnp3-OsRckbLOi##j5Z=$Bp!Z3dS_y0lp&ToCM+`M_Ky#B@;gzW*ZgYpC| z<>}KWWn=SMmg$CxO;znd;lQ%XFdT9U(XyQ>yLFfSPI)~iFv{6YZe)|`@vL@{xeMAi zxPfWHl1_Yh2xN3yJK(16aD|-)a1aKD1B{N)hW62}G889c@{eN8@SF+jnd#t@dno4S zW^!MI2T-bUdIXDtiTHR7libRE?BEaZ^G=BqaOWI??cCS|WwDH&6*fIJo89M@Yj}KC zCehw@Vc`GaZ+==fcKhX+a+<2}ZpV(~4sqb*d02PR)?^fKy!AF^oXf%iPepbgMKmZXIkgYszoL15z1@S?}mq>B<3 zuWAw%Kwru<0$nlEpAqw__s^QvAfpZA^NSkFyz^m7`erZvxW38qQ zy-Yr5XbwBio|GpKJ}w(i9_G#j3GJs3A7%2@Qy{BaUWXcF25J{-61v$0<^gyRKEuf< zT(xs_bP(d;@RuuTWK0&45~M7?rzQ|3%W-KjR)P+EM*UMC;gAl?iyl}t#jI{Za+I)! zN#Lghegbncj~dqmP0qUeo)Sbl%G?y5$CO10+0wbx)d}jq_=~@$eolZ+l(m~{Wfgk_ z5py@M@NA6Xw}1QlWeutM6y|||T;^t{%bVZ+R$07pqwF0HLzH9=H((O?Ub|mz-MU>~ zfBm(xq{cyq+*p4K)7>ch2YWd*&;#=<_cX-T`zRb{s&#=OK!jxuY7i1KHHS$U#H1^+ zU=I8woC#bo33;h-6_vyho;89(qaae510Ta6WW2%(=Gnn$e0(bKa-W2IN@`G;1#Pr| zgzn_?T+cF%mmZqK;`|&8!#gz`%XXe)oagB>>(CxJ;BsVDfN|hHMQ2R2zPT062^{i4Y@`%x-qHzRkUZ@@IebH)W@f7C;yWX03P5Afl3LGY)xq7@_SX6LlH* z(&933n~bZpJU72UI2mk3kRh6&_$|nsqsp9*X$Gbp5_RV96O&L#su)r0W1l-X+%M0z zo|GLJxW~R{Q3p)hIl3#FL>m+SGPVM;=6e;GuX_KiG0jo;I%9s#*3RECs%D;hv6DQX zW=q-ktPYW)yg0j8nlBRdYW?iUc3#lGGPRL!tr|^}$OJb-61coWv*k(*45fc z7wWSTc=izx#<>ZJtV2!p&Sk;~K*Hsj_-1M65FU^t@_}JctZL8D4z|k24<2PMVrA`S zxqbIeBu|&5ZoznMhHri6+ezQNXL>Vb9YVjqw+n%s$=;Oz;(zzQE&s`X{$G?w!1CU` z`{lQP_=B>Xd&YZ&nJaI<{dRftjn@MI&5iZ4v$vh~=$2?kNt|%vr*({GVd>R?WC)Jc zL%^nIA!KS05<=R8AIb(!SV1A@SbGOws+%8sgm^`u)I(t*!z?lfZ1AIo3h_AgTqfeC zEeImR&;AHJJ=e+d&CIGf%vP-jf}0)Hi}Pg>2D+5Zb3NeXJW$=Oot@X>F1R&LI%*CR zz`+Uc6PQp|+EF;NrW~{_OxoqiG7XnXJl)(WfA-fuE&Fcbnoxt%bFkkilS<@Qi zYQy+`U1M3{TIEaA0MR^0V;%xUB84^!Ij9{Wr??I>c(r zG2-F_y$k`61gNb?cKp(B|@Dl4jr2LX5;cJR7Q@la#1bOrMvPibN{XlbDd z4o~^)yn(x<-+k}>Y#MVs+o2R!8(9V=D@%6o{{7OM@1b?wSC2gej9B?PGq?Tb4{*#Yz${%$T=E627>jo+Y>Z|}U ztk3#)OhK3kC!*B%u1!qy*k#3j;MsW|?G$Bp?ApC1%kFxnoQ4)ZR~8ntFT%Qt=csPr z0=NPkTv11YWKcKI<+N6`B@YvHHP`&YLKxM6IKuQVfBp-Y1ez_K!LyspASggyGO93& zaTfrL!31Wb{md;amDk^VBXD$1D)>$QGGUpJ_|$OOy1L)U`Kk={Vf5F$h~|9b3{|kT z(+_b6$A@KCff2#x@zcjV?-cJVw{Q4eS|bIS_&>oUGR%PqZ0KYmTiqDx=XXg&Nc-rI zN#)m1@vQwft|%w+T3F)eyRPx|@6w4swlgnlD3dnsMW!RBc?D51t1gVkiT*;vnuWhm$01RcLVh_86_=06`T5 zA{~j2X}Pkh5@%FXbD?9_OMvKH5+ST;X1mA~GP#Odt>{u~s>!&x^#ut{PswmpsxxGk zY1+ob_b(tKyv5AqE#JhQ+Qt2BSc@TJzyiA*myMqt;N%!d2}$$_!f zbveXp-nITnp{@!u?~nEBA^|&#j;(?3CaA!4Jy~ z7|7AVVO%IyCTc%??-ynB*^?|ie(m0^^4443zJbNX99Q8`misJL*4E10;!>;=;ZqPj zwFk%N$6*p4xsnO&;84{hgt_})tZ;~)ZD7H1gF(Pd{7K)^3hz7`Nb7K5B?<}`4m)Xs zr}+#V_?|r|5^}s{2r4}uDdMI%C#XF$%O#XDjyL|iG-!AiW2rR_O>Lb#2sj~UI z+}pO&$`B;(-eKU8?29X_KoO9Nd9g236cBlnU{IehZ%_xW#ILO?ayKhd>n2AD_7!W+u_WG7 zt9_(C2MLlD9nG}5T%||+rVc?CJK9C8&cfU*cZ*e5SXJAOk7%~lD|H)jQ*ZwguFH$E z#;@g#wf=^;u7V;=4G&8qEKg4lAy#Wq+jD#aoxrqDhx_IHcu)qLkILBqX<_SG*@jWL zqDe+FJF{3j$JlYs+;RB8R;=ILg?tY4*e}yl_)R)2M@Ms26htHw;}Bbiq8v(a7$d_{ z5EI){Vy{H&DWBs`YC7#mS*xL-l-&-Vy#ch9%uh|pBNsevR0%N5(V$W!heVZDty`yQ zSWnl=Pb2MkheTymmQgLI4Uc&(=P>K$DNdM$qcgiZ`{n=h|Nj4G$MoXb&2mcFCZ=c0 zeTd6zZ@fXC6ZQTCV6K$q#yE+&aB=07q-;Hy-~t*5yrCRBk-fB5K6$!R{_JmljuwG7K%uN}ova3TD5v@nk%Z)mMl{c9LLUvgYPm$HMKgQXNjas z4Oau2^u4P#-)e;4tf@u0G!_Y~H)s;qg&G6eaC>jJJbd^t2PN9Zw{G7luit&E+*r9C z?bl)B({r`4-sJ&*wv!z+Regb53BClYBHr_E6;2GN`Fw6g;?KII8P|8KR^K#f3~l$E zhRR#_?Ios#Z_gJl*7AqRm}mDbWSZyhmEyFVs)2NMC9CCZrEli>H{YwzMc#o|3uQC% zjA#3<@w;#F>9Vh7s$tqQEF$fb4Q~+A3`;$V5s?!rr_?g#K@qoAKX$fZ? z_Ho#v)hA2$DW&kQ3=oUIgkJSND!xn|KQ)_-$2%@cH5=G7^h7W_Zs=Kl#5-UY1_jkW zt;1XtHN-5#CvZ&(l4W*c+6iBo#}KCR?l0cW(8TTAcgv*2dCn!ROBv6;50h9~T|*5& zC?9?FaU@hFtKLj6gv7%K_jdNO;!9rnTi^NJa`)!lGTh!OfAMesZTYwV*Z*7j;Jv>s zCum_nGRIWhy?vwHL@Sw{t$R~udmalim*Ed#K08ky5Cx;S*M_iE+qBeV-$8!JMmm{>lfw?1%>zg8-tcY{58HFT3*c92)^cNYr6Ce<=PwivWRjD> zc)Yh*h+IB-yb(>pxd?H}_-YZAIjBh>B*3U0qN?*5Zc3aEPJ36#-u`ZR_Uu`3OpV66 zSXbwITwtNV5MhgSJ%rGqS`9_2W#q3-_+Iq4&T53AxYmZLzBWcQ=^k~pL;8n9$YJ;h zatdf`FxS`byN z2yvTf{+&^xdhYw@G%b#ZK@N#1myFSq$!nl9fF zJR1!=YEs_rTYI)FN>({en?&rWju$(GSY_K+3Wy*;GZ`Lw?8$VNuimRvHb;Xa@*M+q%VmFWSk|Admrp+Wpger=F=2Ph!rW|m?cTlet+(HR z8O&r=kaHV8t35bA9xaZtc^Qu@aC#6`moR7blJH609cGaU06*#yGA=&y9HLK!)toAh z^4@)m(LYXQ25J*EScQvjm8{C&(Xoxv|pCa~@se4)RTK-eIS}n>;)ia|VGXf`qUmj>k~Q zV7wS9Cm-amGO^&AAiy0pz6aKruOpLa#u5sD8H06p=yn<$bB~YnMl0?m0Uio1_TwW@ zFmQ;Pa1;OhM?ZOou4xwyA_gJ9q_rT|`8TV%&cE5K-!IMc4a3Lop_3l?l2FWLWr)Ku61*`aLJ>{EpH(stX*WhmyzNg_dzg&IAaKP#J6hcUXq_tK$Z9+4 z(dsC`vhfMR(B@iXiW%~9hzY`w32B$$lAifn=nRX65Y^QzswYaYpM3mLHVnS~_FLtE z`VNPuxfXL}X|=rl=C_cBy=&P`UcGW-ZLO?7*~o6;gS`XT;&{1p;|`hwjD+wq2{jd0 zJ-Pn>d*6Ax{NVfFD;`PV8Af%_~k)u4ERi%pK#N#yYpO7>2DbltUM(hgz=pwrh>&>Z3{UXbMeY zhPZPu=o9esg9i`GdmnyWHn-8(ET;@YjTT(UVg?GV_9%0Z30Qx3hs!9!fPu3|pqu9q zjXEo!sF!`f(GwZ28ng>9976MG8`BXMVIaUm9JGvh1s2Wdul?FF2n_`f&R{IDZ7HnO zvU)RfWnK-|RcZ=~T}W%;A&=QOdsI&>p7^6b`9Eh)qISf~%3o(LI_nFJ1mvrj3?n3u z=ZRw1J!0Z7GI!5G=DdAA(;9d*eQjkD{+QeI`86gH2q#=Mb?!m8T0(YTo;NLgOZOu0 zk>?B8oBxI1==V!=)z5c*#wC*e9Y$K`_$Kg?0sAAS4@_M`IggHOwY2T#h=r(0!n zeK+@PD|L_x1(L|41wiB}Tvib6!OfzCUOf^_SxXm@VjDa%M==f@uV&@Vsy;ScJt%R;Zb z_4>VX!%1)mkNXQ8hFMv0-9GgskPKQW-1_B`Bg!>_OQi|pFdGR8E9x4Y0|C|g)N-BYpbS$m z35VOfjn3mZdMj&XfVTFoxCh=HQ)ef?Gc-i`te+t9$Q8>WL-2?W@xvij`+{>91kCPk zwF!@Gcggp`{w{e|hE<1M5oCr(k+9W_)QB~q3)EGR$_TV!x`fZ1X8@Alub&wymYC4$ z5aEm$|A1V+%6z>bs=ldl9A-#L#sZUg2Th_Tpsk(sdiyFP+Flp0S(eN)Y>1-pW#nF}EcdID_QT;A#1#$hRTOA&rPwz$hOhz>c-DcA1JL6+L z;dIpRv(KY`qb3~&VpIu3CBSvl9S!cC3jO_Zh6|Z46Ck)-@B8~6hrJM@I>vkM9=(UzP_5Dh|cXkhZ0)dvgZK&tWg& z?=dM8R4ypj@E?%7n#yycauB2f3%KgRgig+SDb)_zwN@r_h}LbJ&$|Sg_6X4B6c?Bz zj0q83?fgdC=xb$0idAbMK2UIRT697GFehinm8l~sO#Ew@M7U)>`CvlV+lE9h zGy?CMc+DorHU3v^E6t_3@}4l4<`t!Sp}EYjCTX)LHD6+Vs{r*kxT4X`=jU?{{Ovqf zYz?QY>7Fm**Jq8_I3|$aTBD3S8@l;jwTTLoNKlBg9mJsx(>@&z$_bK`E1c9eJm7EN z<24}io_M;xv0WZLc~<`Xul}lh@W}(TgokB^&g&h)H*ekU_72RTaqQ<1xI_0^&_O+m z$YCgtZrFoC9D`Uxi8jQ=;}9GZ7H6D$kl?p5VpryfN)9`DkFmRl9rv%28J(N3nfJi8 zGioB)lD0;|5RD1K<#1XiR(*%yIeu>1rc;R-R)UC8;xr$nP6>osfWuE8ee@x4@}ipW zme=mxhY2A40=H!d)#~bEHj3R^Tg#ozYiI+@Xc69qwhBXVdFRcw)$*;k-h`kYmYX;0 z`9&@ya6ZV5XD$)VxlGwfOgU^9GB8g!#W_sn5S>FUuH33j-tR#uDsSCveQ?G4(T2LB z7nP5{l}`V3W}go}S2*Ekd^yBu8i5zqFr7hfnb2pP0+vm6fJ5dm#<3RunM zb~vvzUGB}}QXe#dDVPQoi)J(iBN@k9*R&B#=Ma49dk)sl4%!EjJeg0crMc2;9!3E} zkXfv6@0Fju_kMW@ev&}olk0jjf$p+yv|?~*W_p5jolv)(#i4qxR0J`~EW=ztTQh9# z9)Vf8Z)Fc5$g`w&x3_X+io(F=7Fr`rvvjhXovh6?lc{p(;X z#x+H;U7NA}t%g0$pb^Cg(4y7Vne{nLqCR$sT$6Y+LAaNhmg<)@B4IO)cxy!8(f39; znt4U3K4a1$Nbh-D^OSHmzvLXhn)g*4s6_tK)Ht6t&9|kasp(#clU`p<^M6sAS524% z#6xLM!kDpppDCkbZahfxR6`*`cQ66gUU|I!7`VXz&OH&dlVZsuM{q+FoYR;>nwxgg5h>XfL+;$PGe@ll=E7YG{siJ~ zy&O7lsKxn=$|Nj0#|RogvhNl4RNHiD+xOvLE`+QA=xH83tWfW zV(7rem!P@A##KcFh}50ix68*LeOx~L=$BcpDKm5EWDY5ErDG0#>h4g*&9&ud5CujE z{VBI@t(CjCZ}LppDA&x46M@3pA+X~RDASpmK_dcAG6*NzC(%YSltKL){G5kyg_wIF zEO>2mAzTT2n4?4p-w^09MR1e)rcVL~>t4>yUxS}U5a};r*DGO2Kk&)LQMke(2}t8C<|9OIlQOFH8+n|l_8!|7M-kyxjX6Z-PO}D&;^+4+O1o$C&ZJ% zIm9$TGu_+XEC;*$;HL}-81-hsx3y>>le6<>s<%*{f|q}bCh_>$v#c@`ZVCWu!VVKz zW9JiW>BR+@6L8Po9fbkHI;QR|Zih{cFEbNVAR(O-=k8 zn1liSm?329Ew1Ffrf}uCJ_I>CH;ASy;*I#X=VpxCY%`-_BHfI{zjSN(i@06GmZL|o83QZu> zxOe|vxp`wPoyx=QToGf(bybN3K`lfgu*vv38QEFpnYM- z#yt;coOFhibqV5+Xi?|DQAjMiHK z;l7!NA)&Ihu~{~e*mohoLo`u`B*nYcTX)L*GFmHI+8b|wD-7c2@4jFD;%|PM;YsJq zz=FU?JQt^qNYCBY?t@rbm@VE?=g^a@c7%^w+D$hnlE2zRm@MUumL)8rRiO2vT|0kq zLKxF@;N~2kiLxu zY0tKqxFsHVR#T%XiX|S)bE!!fri&%sU1wh8-;AG4yqT-d?LCP767$*5m+5G(es1rd zmq|49eEFK>2?BNgI-})oo$4~y^Cfvcy_SYeP|fAjrT=K0Q2Ljc=fYkw5(Fhm2@ojD ziv+4;hIE2skbbbY1%Wtl>MhKa zH{QHoo^3oVt2b84_rCjf`N0prj|7G!M+bH3rYCL=j?c?K`cM9lux}!XZRA*N4|r3} zcc^D?&;0~v8Nc>=Nr}rY`AgW=Zrq^w7514=k->G$JXNz()9KSbu@E`in>tH6f;9C% zM4*f0TL?m2)ANzKnZ68b4&t(c*0hYon_(ab&=kO&h4^`Jof`}1=ch9nJsciH5BEV7Z4jIT%RQ}Dgq(=R)>6o&mn5v za0f}G?-(X^s*H%=Fow}Nv3w?8+!h|Vn0{a&fC4u2lhFA>ipGsUFNt!V(_kGcv|gT` zN)Q;SJM|01w;ny>Epc~m-OljTAnWk!a%Y*0aZYUKqtmjz@vN*PkZi%Acel3DDvqL& z%z!^KiM88zGSoDLF|NBA@uLs3NFoe^eAD`tufYbR<{*)~fwt$fb&&AOfPbb0u+Ms#J|vWs)!rhgTnb@}N9%I0~U^fRHmYH3Jjun1zP& zeN&7@)dJRzTG;m5imUn$2PdUJL@4;ze+rW@ME614Ob~3uTz$W4?3*t$6?rcMjXpQi zkpJ>oQ{Of5vo`HnH^1aB;=II+=4V+(T~iTJT59oc7QY&!r~YFve*&CmpX zp7!c+it`6`m_iF)5Let#n-IRHA#)s?a(=;Opzipt8@fz8QYGP?m?m;Z zW?@1~!D?})DWPrY^P4pJ0&{ed8BKzub80GaJif(tPykqm}-zEH6PK>p4yOC~wVX1ugd%sow$v^qSbRx%dpCCQDUfoGy$Bk9x zJ%Zd_+IC3KKa!wbXNA4)C_2{_KC~CaDDxB4#dJJjR5#CrAB9iSGY;_~znNt3yV`}$ z;Czgi>$?hP2w`&-&OnU||2_n9aClH9{z+h|JKZ+HN$ep$IdVi2<9afT@W=A;;@Kf4 zt!+_{8{xZFBYvqpP$sp#T>OHqnuI0B>0l8P%>gD#IwTfbnd)VIZOi&x^O9J$XTNDo zufaFO6Tg;^B-6TPn1XL74&4QYu6S~Zq-RATtxqGZBLs+7GQA90Qtts8>h{z1^6Zm` z<>C7umQUY%zwDr4PM|TapncxEcelLx_FLt3?7cT%&skNc4xj=Nx=yNk)_50^BwWD0R8VP8#pvXnq7lii(#_+#sV;Pi2PjP*A z|A7szwd@lRdWVnd*eS%U3+LEzmKSa$-grJh}cMIcDsAX>$1LxD@4)nagSHw1(a>POg4OX`?~q&)K&5Pg}& zxot{C#pO{3@P&sDvbfY4wOhIC!b;MrHM{(}RBQ9JiV zt&7LdIOnno-g;v10(J0c3-4ZWQd{E&yl;%LX|Gz$8H_lu_8Ei^`}q9aqS|;xh*QW( z2uc@0^ZfJ3%S+59qJH+d<<-p9=db$xRi>4vN>rDfs@ayt)wFznRr(U#U$>!%FR`@_ zVGt4trB~v_LP(k>;aYUB*{pXYPsC3vOeFZHC!~QC@q54b56fF`eXrcR`v!=zRGvQB zq*Fp1__nyPT3&nYjWCPFg_UR;%S)?h7XN9Ogp5acsX^>)Zm1Eg1I0_*$=Q?J89AjK~zE2-s~8R zoOTbgVy*P38GXI_?M0>$su$T&Gn(dg>3`Ml*O{y35n)E(HCNNRHt)`U-AoQ|>*@i< zr;N63q)a-Oox~0$k(5DX^Aegvj!%G~O;7d8;ed{DK2d(>hreG=hbLujX1@IH@BDr= zj3*DDl%1VDzLPF=?4u7KgE!ll#i+4- z6A*T_0AZqb;Dl*gWi$f=nCZbNV2av>`4wCk2JRfpV}5ZJjcGaBRJ5vDv<<9rJnJgV zMhy!XyPVVEH`8`6h>XL0W4rQRl)JM^#~0@rQO`Obg1_G|bskHctwT-G{$vpNscWRs zJM&z+SKgbSrVT%7TX}@J8ifSb_Yh+0p^-pJDD69bcYdi4Vc*%=%8iEmXltG>`ryHX z5ZDD^vNYE#Z``?4)({eIEG?E5ga(g<2(hKe4*O+jZwP@WKXG;lr4oN631J=j+V#=^Jh|tkOdFIBG`HGrn)BKhIX;i8#{i)~UcYKX zAU)nIf+arfuCnJIV9)32CneZbyHYxexb}| zNhL6pC_7w)JB9`|?$x4b4Kg2(^qznrc;AEChKC~7)lRtNC&8-aCOUSaE35C8KSO4z z10FERigys9AYLt_!%LPo!%Q}EVv1k1zi9{$@(IC*h|73*f%%Xm#8}t&fWxhO z-Z=SL&o*~s-u|5vagTP*#4q`~Qq2vCuJExu;@qvVHRg-K}TfZQ5!>-Ne`6jZTFefYX|)N_y5EHRQAy%WUwceZNeqg_53R*#ML5m z^BvlaIN|;aDp@abT3baUaHsfjCZyBmVg+@zo}T4o`48z2ednVf{xUW3!~Q^}(q>`8 zz#^vx!$kJca`s#nN}0Sz+qpOQg2dPyUjrkWd|^W*dQ;i!0}uMP?XI>b51jZHKXM6d zMZ#dAm@#52iqyaC`n<-!c4QzVLIt6}oN>(8ltp?wu@aKc_L<~p9)3$FYGo10^U!tR z8pl4+p*c}3W!gLElZfQtP0H=M_;gZ!3}f+iyTofee&brt?yo)@Usq!0uMEdH5{4@- z{`HKRk$f#z_g%LV0Sm*w9nU<|0jniQ{fxaVQ?))TIO}U2V}XLFDLH<0emYFYsz#Oj z9ArPtsip3`b~&a~y$-Q_@4Mg4**1$vfF4e_`Q%ZVnHbAXs4GEM&?N4^{zkcd?|zw?UxYw=m|G7? zdzQQ>k@S(|VK&ynPU&P}7$2Qk2H@^jRhSG1;9jiO3EcVRy)KItNJ0XCKG-(G*X56D zP`S`3xKs&&lIYCLT;?c36vQF?9qaepp)m;mna|$qpu~z4?EJ+PWu0&%pz{?F%UlZN zu4+10RvXz$X*XMo{7HX;Mh?Ss*Ew~dA+nh)W9$+qTsN-e)@!w$nBgavT0mNEz91U|>pCpDV!tVj~p z9vLot-Du?o#Ff>X<@U|nnT$R{3ir;2WzTK$RMDmRaua4Txs0|7P8^cv5h2++u9pJu(i9PQx_L%U}QW=V+x5XcHL6Ob;z(5A9$s+KcVwJi^#HgnqDB=BCHX z>-X=F_d(aMN;bYNke~g{oz?oazT&YgY7%Y=pToR39g9>;ZIG+sURpjrorXcw3Ts7fvBFpq3JIqs zgq&x;CpUixny;OEY2#bNckxHdL09WsiGb-q=CUh~mhXaZ9Cm${f)zUns9o<{xK z=Zhqo}Mc_ zyk>}nGRxrgP%773{Gp8^D`|Ol_$#^#0qO*?45VrjG7_0V(t}ESd5$t@(AFZDFGZ6; z`!0U?@!Z1{trOPerw!}%Q@W{GX?YamWMncOLRn7n+5CcJxWo<|%tK+IV-Sr=*uWku zp|vpeRyd!{%O#!=1(-|9r8iMxbS(xRS=bP_t|+Q76Lv6I+HrAtIh)t!9L6M^W%XVW z1%rhZC#TUEX>*wyIROv^62dt4?a}Nfw7utf$@mmho}z{P{M}!cj~_lkgFt+6?nrzA z9xhpy0ZhBxG^>zK%EBCFa3h^U5M^zbW#!Iu-esB=c?e!Qub~yk>w+CDjcr|~rsk<9 zAD1`2{hctj2Ci?aq3N>`RtD`T%WMz9Ny!5< z@z4JFPv7Z471N%tvw`#rY(<>vzQ}4u3IA0lpxhHigT2i2(j}2=ziF*xRloJFNMRQ; zS_lo+2DcpPUvWDkVI15@Ub;!ccrCtRm7MIb&--0G>tcC~NqXH&dv5P9G$WrAzH^&t zPow@XN|LHkE}w)>9j1{$INan)qA5D69Z4zQOI8-qAnv~QdU@lGH>sy}9n0Md4<9@r zzq9V(vr=a0DBk*|UG#jNnJMxCZlu4ny@6nSScYgV1DB1$Bvk1wu=FlN1!yMjC$QsX zAAzNd^n6x&y@hBr5-|zCH@}&7Bwbv0)<)w?z3BY3m*EHwXMd&TwiPDJy=L@Fi{%Y0th~erw@);K%ZiPV-CoC@+4x=3+U|kmQw!BgI?S z)E9yc;kHhVXoZQ%BrK25mX&sC-)b=oFUX*{5b+BJ0Zi+PFFuC(kS}m_by;?<3pcF8 zF7*g+qT7k;Q>{){4R^d--fYh7`j7$CqFwahQd6aNDnvH!tanZT?GgOwp^f^UVs>e^ zjenljt5zbTayUtC$vZth`uIWl#e2Uj+i1A1BtwOZ7U3P$3R<3?+x9ew<1!6bpn0@O z_I;362)o09XE%-6#(z=R7n+gJ3E#QRw5L)3i_f~3pyFMI*TI6`F9TGQa9Bu5)*}eKd?#82jAF@k z>oAGe-+VpM-I(OTbROaG`s;Ty_Iq=6wRoqq$8apF6*wGZr6CTdXR7c!5kXRITTt+H>F>zqO@drkOi+gR5K5?#FD zgkh{7(NeZB#L6Jt6`aXo(lu=*_L^4BJ40h(5LO;Ph+J|^*-gJqC?x(G9fhu zhqTlZ%rnDte9O&j_*p)`CI7BH)M}b(u;XjW<_(3mm*Ly$H7n%gt&_$Q>NDE>l(r{! zCYG~m&UCtZ{Bu5|?pRt;(!nFJ-4cD8KmNqw?wFr_tQT#vOiwSd)*-Vk;As zcsnHIu5}oW@Fq`p{#&jSV5?CWY3=6fC~vL{oUyg-z)f(>rP_Dyz7`?o=8c}arZkgu3NY7m4Eu5{paQN?|naMc&3$eP~T)@bDX8Bv<-OSk4tc+UzsjH1V&LoQoh^p2h3>6H-wOpr5eN5NmS7bVTBpr#8%xJ6}!w?>BY?XI^ z`9ay-*(+W?q;{bM4?uz=GCUcqFzzATI8R`^3)5vJd~4E}iFs)~#a2zgrP@wPTYSr8 zwXKhHNS4j|tdfQ|6}s<7CZV9@#XKaJvK|q>H@}#9wHs?U%M995We@_*FyBmL^@N@6 zGJqkjZ#*qe9zV{pITQa4Od^$w1*ieWmou-5I?5b0&oPVq=~hTz4XbI0`yvwr)UB_1 zmza4ri_huUtpoGyyGi=3hP`|qwUJahx23BceXdfwf0xKP`n|os)Qkj4oX%~gJ&pQ5 zm+T10vLeVb#S+M6Ef5ELh?A!h-W+g-wIj$R=I56}Nc;W05E3;6wa(o6%kz>Gfii{= zxFdU5(mXlxR<}X%kUJ%O&+Ru~)pm)#RF{xh@|x=q>FjR2YVfo|<71w{x&YCcsRWMl z$)voV((iF2k!ov2FUFJ!U==0Wfg1Iz-;7%cUyOKQn81U7+ytZH6B;7ig{#52tb`H}{epQ=@Hkm~X=35E>s3uV-tTCi%y_}D!@AW~#s}`Y&mO~j` zR-An&Fo}sV^CA5Xik{l*_`Yw3GfkJ)o=_eq=7p4#-!cskhuk?nEAM{tpuGRlgDioa zoSF^T#2t^+h?XfHQx1iOTwkgt!FL&hOS;WNW4*LqX5^|Qm$=Fx6hhn5RT)H<)(#KL z{{BJkL9uoo5u;GxaWZO2OF7pIT!b08SimxQaCx#h z%b7p@)CO&d<#^@U z?vo%iwFF-q*^G!1%+`4?Gzh}Ba0#1m*V{|!u;%gnGkI!#Gf|%}JujXuX(GJHju^`v zZ`0_^b3rb?*VmY2fFFP~HwjFbM5p3e3<;CpbLKvgEv^T&Ip*u~P1SmdvqvvDbTBa? zQz1OG-gh+z=O0W_mOu}uBYKz`#37T(RZ4Z}#g3dak{oWLgE`(SadEQK3)YqF>d=tV z^JMW-870$b668^tgv7WK1Z!;YS{sO52py6wPr9~ma3X0|VA$y|03$rCvCJakvhdNb zhOhWd3}L31zN8!N$2#Mg{E1WXw_4-W(?lK8!LMTg&H*^|bA}|FVU-YVCHYz^v#7X< z6~7=rGNPRA1W}TZrTw*rB}{T8kFF-Z@h==qR}F$PByZapi`z6a8Hn1WWiXzMN~R%G zx6ZXT6{bm-Y!#-cZmc|nuV$LE$t2u=>NTiw*`M7@Wv-=vv;C8 z6Y?Z1aXvUYEx&m1xcv0J4|7dv4wUARdWxJ|C$$ z^WA69pYo1u;cIy3K-|$Sqp+N=Zt|L55ATyX91ZJ9uri4S1SpS8cX_NsSnkNTY-(iuP^I0|DbiuFqv2betL8axrJO6~Me%;U<`Sl9;*Sm^svU+nhlX?1SJwACF$;y>cN~i9+oz2-rY6X?)!Uv*FI9uQic1o5K z5uaz~kj9o5LWBcL2#eC3W7Y}d0e5uV5DkZQkS?8sup{Q3IN2!3b88pBTPJrEXUHT& z7aGEMw&RV@o7P5j2$`MbZ5#PUaW!d5L_=6zJMX0IXZ^H}ceiI32efmSVj(;Z^Cb+= z#%nllT^g|s!KGf;;ohk6t@-#()){L!2%TG#~)>LVBP6`ibgan$KbcZ;#+ULS$_C~9|XRC z{^x&Q-v8yhr zmd%EU91}(&dR8?sqtc-qYmRhGIHgYycJl@@vCZ%1tNPz_XDy7z^14eo1d=>F24k|V zMj>@2G;hMQJl4#1ldxG-JEl^29eR?uNyv>AG8fl)rjdH_Y&kNdNV)j&C1ud$d?HME zv8({UaVekeVySC>!k}}pRYN(6){x2YV>CXV-Irl1K4<=ku$E0XjG<$W!qAmYfwe0U zcrZ+GhgaLkAseeLGm{B4Y20rP)46PNT6j;6p_$4cCd(msnhV1M%XY5AZ2>gQ#DSfzgw34hcd{IOb?pX4s*FjdlRk)%F)3_)y$x;2-|?A;Dn2PspFPU4BP(l5 z!nmTTzu@|>-H4pcj+)W;rU85zHw>cH3Afp1?5w`GIGR!7`}fLZCSOvdD-0xHrw87eA#bg@Qm>iBk?65(-07k{;(tEs00{=9na;6#&_eH zT8w_CX}q+NEoYe|)Rspg(D_@3i#DWA?I?+87qMy`5)kpK5;Ylt@vb+JpsvlUR4oCu zV^=Bvs%^$+JAZSpT5(Dn9Mc*}%Bt<+kEW-o<+m=>0brO;3-_XYv=aVG{3)}~_z@vm zL(88J7g~fZX4#t7B(rVi0=8F7qX$VUMA@p;ay3n(m0vAT>AvK4yz%U$hJ0rz3hAK? zkoMh>*grZgyZyt`AD)y$!tB8mK7F=Pe*XT4Ie<}yaClrb+N4Wz$tfA@RE^T+<|&;BgOk(gfk$%wHZd=m`Ng`uHg?Qh3D zIzB+dJ17(X?H~W?I}J(V`uHWS&Z~?-Y_^#oTAoC#&u2-Xdp6(t+|iX-pOw9oG!#IU zLTqI7QtDAX$2&G?k@V{Oi|u8c>+R=B<*uG2 zV&{nT>6-aEhHZOD05T>{MviTto(@YcDN;%$o-j0tMvzS_H3qJdA&<1k9SyiM)2?`_ z=NHw^C$n)fb}~1W`CT$)hqhyS<)s_*lu&I8)3yy=<`~Tf3gbyEv_}OT}-37l4{&A3ard7*7h}DBH~8Vz+OH#*qM~@toZ~C z!rFZNZn?02&RzvFqKsUkjfC$`^;6ylhv3xtWI08H z^nBHQ-aq{GVfhb#`Lpt8fBiRQ0&U}%@>zQ?t8$68#j)N_B&)feK-^`D;!}hSis^8Z za}Hh<<=z^HDb*g-8jS6nghNxAxF!u^;~nY%EUc?=u*mvVT9LE~>u^&n&(S)mqb=x> zEpNW{?eg}wzC%*uFp;Op*PYlh1@lR}c2=0{etiwv;@M%@+Idz!efSZY#HTRyJ%l^x zWtc?Q_+Qn0o)oS!2u%YX;LNj4^(xo@xR?un8cA1^cM&0O{hrBZvJQiYP0)%VnCkap z`$`i)eg!jajg@NtwL&doZScV#2zSm^<;k}mC zM`2;U^|`vwzw=aoc^4`d3j_oXTP9MyYsLn|Snev;6eE56a*C?R(|Dj~|qc?Y**c^JYLA znSdX0R-2=`7Z$@Hv>w7&iLUJ-F4i(19}dDya;!V`XyN@{=hmurBH%5rX|yoHM@Hxn zT!cymo1|Ln=t2*NrlJw&ysoLTcJp?5{mr+_%JM2qW4b(D-^i%~9)WKB;5P9zqt9PY z14ArFWn=ScdGzFyvJJC1Iz5c<#6SPzpS%;K)>K%3Y4drbH$>Dl#MBDJNdBbc`-@!5 zJL+D1C%!3%xcF{kgKTwQgbi(YzuOUc2BQwz*3D=b{XP|>QW*nbLsZR*8{uNG!a_>Nfd+3aIl-Ots68~8` zP-O&m;Cf88bc`Q|zDPSa!8tz6vmHm{TtZepjZdcyWe^fKf)ExW6@1z5$CZXTwZl2YzbW3x7s{vNZ7i|xLY|)zrn6pFf7}H+-f`vVJN}~cFLME+CF@jo7kHi4ss&; zRLu^b{_wc$91JtW^mt>t{OsKi%K!YAe^dVQXYZ8mH67bktj21iEZQYH7u~Q4@fdY1tfSzcAV7&Ag~~Ny;-ee5V5|yO39AJGwBe8 zJRl~x*|>%l(XQ>xrYMP&M3eTJLdsL~FkA>v2vQw(i1z0b?{QWM|ckc@CS^AoCs71&igq>yTT)ro6U{h1p zw6a|I@+>T@Uh31q!SjvccJE5yE+vIRliztA{((vK50A^{-d=gUzEz&ASIyyP@4jFD z`scqaA3c1MN$L|Pu}M$jesbIoVa~?9DR72Lq?~F)un`zpJIpEAXc@ z^K(u z%3)NQ#Om73Y~q_llK{Gz$drs-NWN1B2uDEX@m*ooj8 ze5{b0BoPU)&vwMR7Ji~iVII=fX%P~0JH6_A-8WJF)jUG*Lv&n;MZ1x)Z6%XPyYo49 zvK}2CM5~dw^H)h+1w`Wc+z}g1@WF2#L2kHb!ecNx_jgo6t!w;%DyD@U{a&qkAzec3 zOgj-`E3qbY+=RPGqsD8`9hB1={_(|xOpT-}Q5P;Uh(_!y)4)QI^%G{bJT@>n$tiS_Z(aoI(Z-rL(R`w&W( zraJuc?k_(qKmFTx%isR;gYw~nhvic=hs}Kmx$v5Sh)+P+DWgYr&p?!1K{rL)cn9^g zM0!%jOa9cybC!gNE5O>lAZ@RMunzQa#Z#?i43zjRBdK?J_%7V4zk$S2H|6CJKbZu0 zp!N_NK^pG6kVzP~f9P3c;I!H@))h@RZ{NxgmnRx;Y;A=hsY$epnzUbkQ<=o$^#^5R z^GP{A9|C8E$=q>W5m6IF*8LK;nGj&oxz44zFI2{vu;pt}D-lpBNuY=cg0oI!-#9+JMUi zMgB?@=x!HrKyo^dt3=#c+pL7$rH~E{WGE>R#*#+5EAewYclJz7BiR|Ru0Bznx0C8t zqDdOWNgCACbbR*6<`B2eHiDWsl-=PO=R;glSvR6x68&bAW~&V4Oj_ipl$;58;Q=fJ zuyOrnJSQQkL1#5+x)6nGB_g<;b(eS>PH1Jl&eVEVH)RuU&0<>IO2nG<->t$?PVL_L z!KxwP$^c{ponO@=YJW(Wq|;o>Rli?vYB`=awf?nDhz)VCI3x^f5soNBHm(5!uWda8 zCg+p0rGGkBo^AKbCyzJE$B#D3;P@QoK${^fh$G%&w?F6y7R$@-YMzAPAIHxns3&Ly zwuzFt^>Rt3{bF%`uBGQcmA>i8iZ>uD2D{m;os-BrUQfFrLN(JQQ+Tf#ugLCuo5MSh~=@M5{qgn zPV8tqNj&t9ON49Rueh4j72Aka^Sf%UhSOG3i67P&v0d>rx@m`4)1W+EfrIqG&yK70 zV|D9$=aq1d^D6nd+CxcHsaisZpac=G#NT|BLOm15OqA|IoOl+ALbxD8R$E4)^ffU} zhpk*2#zLF$?xbUe4v20zJDbv<#m=}dMAxCHkhOELfGm3M&#cFMGHwb3*%N`=vb zAh^hmwVpYM+K%sV73DLr07#e$9^wbyZt|iYhQZ$>Lfr6o?wklrOzozY$9#+q-oS*& zhs}glJ1PQ;e zF-Vw5Gy@rf_|7wgYV6$OQjXCsc$T3+z>^aNcBNQ$!gpmPT8w$SKp+#sw7I+`S_I`4 z*MxyM;<-hZvU--);!cd7nF-|+dvI0`oGw8k_ePU5 z>aUREoei!=8iSdfAfZnx2~nAvcP-=TiJR~$p^jEWoAEW0{`?FCdv?0afO9g6De@i+ zz2WXC!ZRnjqw7jNk9A?CPbBTjk@u#&gJ_RS7Z25_eJKqa6z1F z?5Men7w0)M>UT95*(sH>PQeac34%ZI&rAAP(j_AW zV)0!@EaT6S8gwY#tWY9ZhYi|#}1kK4T(7!2$p=sFU$&p<$VU@XeEs}nyyG=oLVm3YW?os z04o)uCK6Ntnd*y8hb)O>xr3DEWjeTgwl7p8G%=*x1gzAFIwqem3jAq{NYiJ-uI`5C zy%Pd#Yata};JdIhhrIg32g~B>C`*-&lKQC;k}K^39VZU{z%C4$be&7Eq1=e(k>Jz4 zDKrV=OhIsv?6(if=I)^E9UhlHlD%4*dns}Z2*z`p0s~&N6x&r-w0Sf%hadUsxj#4FF0nkqf& zP?!0dD=_QA`RKjau;BdePPOUv3{fnWbF zpGBA&>IHvQro)1U$&8F!q;Q1A;1!NnTu}X)bfPjN!2kjgGoAn z#(3!zb!Y}+Kp2O8>ay3wjFeZ;C?bpugZ#WG$tAdx9ti+0j3axEOB9Qmk7aP}yX?V< zZ4wHhv@;(Ohcc&(xURHu>5I<<3zL9IX`{jN?w`+*W@Qx9E^QPiJ0_4)TE~i`4NjG? z`zRbLu?fN9v*CqJv&|S^!lW6+e@(*T>L(E~4~_6o8Xd9H<$?c>n3%`jaaWEyK(oV%!gm*uPF5z>aoUq4Eg$!fCCSw{2oWf7^`31@|X zBN)W)zH<^gWeY~(Y9x<*(Rk>eu+lik5T?!RiA==tZ!{8D$+dgO!?1-Hu0^mu^&BOI zm&ybsaI`>KSzQgjrQFujVX&-NvV90gzWO&ppJ&241ge&y2AOsy#lTB=r<@Koq9M)J zO>x#=YZ*LUR(MU#^vcq$J7r~M&B~OW?JXEjuPm>u@V(~cwYSHlX{y0NT=(`|m=3L8 zYP#S$SM66Z!ti|D#RmQC5ceK$wW|{}isy_~s{WcY$UuA?tgMY?)JJ^WC61lh%R{Z?lI-MqC-y*vms57JKg&|<=bPicLgk>7d zROyX}h*Rb*!FH0d&LyC?J$PUo(u~KCXK#lpuuOvIe5cNJ3?AY_!b)#Bib4sO zI%HxbOhT7%xDxtt#p3qeI-Sr(kX9*_6^dSy$Rst;4!$ zOw;ei(^U9S8~xEF_I9?)qlcfCrw(2+-?Jl#av7V6zo@(D>mbh(Wq5J`+OFn z19wCac%@YqscyBx8`%Cw^J_L21VUhATPJO%cHoA22C-{jGJ*CzVI;n`8&(a(aMLga ztz*r>1^gUu_E_lCEL*%JTrK@(?T=MEkoe0W>^TxRiK3gGU<4LBf`oCaYXS5Zr_6EG z>RTB^wI&%wi0or!4qe%_dPY++pc)G0(8`ozqmp2+e7}Uth@bIV_|IcQGHQLpq{GCT zy@Z?Aye{6IcpYKh?OS^uHSPVXzb0)BA*%#%gmH|R7O#ERYV?;e3=faVJGBVYlxRCS zZFx*P@l6xk(oT5mVXO1mWwYD62W4lkj|Os-+tTVz__18CI|BjE3Bq1zG)bERyAy{+ zPLImRpL|lDK7E>eO;ZLSlW#FuidwfBOrmZinj(wkkN-jzbvR>sIE?9>{8^1LM|AwQq3$a9??P4lX$ z_%oX4uik#$4IucnnhO{R>^PS>(sX&xkQ3HthbdY|lIZIf0``J}W{x4mId35V#jD~OKYFObuYQkvpy}6R! zOD!UP-Mi1aGL#zj(rQx1!1u+*u!cz;N9x(iEZCffNd8g_zoB)QgD{g&Ds7vNVSIOp zsY>mR=}*-%+B&oqo`JdFjpzP~smUIBPvbvU4v&z!`=sGHPlv;D2vJq5@X$!-upBZo zp7t1x!ZP@*rm()gp0k#kcHuYkRI_ks%(9!WjKVk?>us5}3M3la)N(iN#kzU7_8etc zfI-a7sd;!I(Ru0b@0JH2epuf7=}*h<)_R$nMhd6Cp7EqWkzqEVbpVstL8I9p!aT{t z-sRL*j=cI+n1*^^)J>n5C^HjiZnG=Yv&T30Gl4sHqAY9cjQnKOj!OKmvf|Ur?5hmr z`CqO5yEG#8RYIt-BV>3f+liN>f&e7`I8I#3PfXYIZdr}hG^LqK3j zOQR7a^VB+&5Ln0%=!n^aL0QV=6m}-dDkpk#Wo%}aPK7_;>v*;0#dhP@aFWa~=uZY9 zo~xf^5a2m(CKky*cu!uwOD4Qbr!t5-W-d{78DLuqsI8O35@y3F!K-1Y{Zs<0X|NoH zYcnCh(C3Uz%N%$IjQZ*uw%64$=P^0fJyA` z4YGmFbC|aGc5?{eq1U7ebMlJ-LHaT zE7G=3(mI927YZA{CY`0D(}^Wun%0S~nq08ch)DOW`ku7;9-#x*Z z*_PIeY~4ZI2vBpcHx03Mn|)dMFKb5Af0cPz{;gike#Vfz==!o6ygYs4hYW*0J-mKb5bKA3F+5!&mf^cQlMf$+n z=Q`(rPX4s%x#U-%4GP3~Dou7j-?3RxoeOlJHw}KqA^n*pr;zL*Nyy`z{ z1kh&_c-{~udHFmN7Le5Bu-4}g`0k?#9US(-E5790l?>zmyw|JE7Y+X(&EL7XXy*>u zl;E26ou2ocU-Q?!YV=PWOtcJ$v=X&Ml^33|aYaH;&{TV<`AdxJ3X&Su@7_V+8Ej!& z5Q@oZ)ZX4gnVMNBlMsP%7zLh4|C10Kv)ATq zZ80W6qs$Ij^pA&SNSWOnrbct2HSyi@wV?;g=JMMHJBiPzX)vgL=F+~(H25_bUz*Ez z^ST^d#O&8ThWvb;6SRa4Wrv=?QDFgEQW60YBM@vnkN_Yo7AU*uhfDC?aK zM|CGQu0wgwKV+vn2@2z!5No0_<6+dcf%(P`xp-hYdkjLk{ z@z6NJ!?e8zegQn|!9ZpZ!aNc8$&<&$ON(qzVwU~EK6wrj@AM3&rFF%gUxhC&IT!S* zxW;myN-%(Ob%Z)ZT=z33-|ORx+?0em>Be;aCMRFCJI>J0R#$G7JGb8`x7Y5Mi9h<2 zciyr328b4c z)Qwo~yGYG>Z_VQ7ux4J~R+q*O+uWvgi3jG>n1Fs%ENv3l+djavx)M~!%B!DojH_wG zgEcM7S?if3IzOLVS#|PEJ=2%@SeZm6RDmepDN5owM5q>F91q^}M#I72usnXeUOxEn zLD@Y(Goft`DYtQ*y!E~hU5n{nf#hXARwo^x!x}tuHwXdM7{s5ZQFzL1^{Y(Dl|tT} z=Y}{}SvJj}wxdItZFsX|a9!PfZr}7)<1&t?1c)QPd+bMB&17H6d|j-k1XNhmsd+YUbhJf^N{YiPU@vQWReQQMBL*J~NBTPv?`d(7T~1SO|ih$xU(@2EgBrY)?HqJu1VT0P00a zr@*qR^Il}6lxIhGQ=rB;As)g@n|f1HGz-(ML_>c%Q;1Quo^q=(taZGoehivN;)TS2 z#x$aI3A5_gjL#wP7}Kxsd=Ety?hfJk(Vp$Q{xU}6)VOIg{LDw2N$@V5ZmU-qZReN% z+J#Ti^IVxkhUQ3HmTcAraJgpY8T64!07t{h{2iX_!z4cb~f%hH})XWoXW0j8SH9!F#r`9*yV_4M&(x(jVOX zDNKZna~c}kCpGk^tEz5bSKq?i74Cf(9L?W!$+lzuz&(YpZI72^fwCFKI=W#Hxc_m- zBuudGaJ|gCTK}&4eb&~W&-#B6o7#K@bAcScA@f!97xphRFHgS`hl(oKg}cHeRH;F_ zNTKvJ$v~y;bS#OwM2YXN2@;zeI#R06Y9Fi}tL4(9Y9iLK`a#SL8_Ax(jOBOb&*`sp zwxyM>ECc#|}*#4a*!-oAY9J)|w!3WISRn1n4Z|$w+g=r~lG{NErrmg7l>=s_qiX zOn#Dw1eP+N9}(to7+bX?hYXx}CQY8z29g#X*?vGJc(%Me;$KN5ZaxZ&E8ltdC6aL$ zw^`p4hp?mX&2Q8{?SsAejuT?p-u+ZPeZrM!@N7MC!$6Z}O{F6x7vUvxeygFYpT82y zFc4s0;}QnPXw(9?#*vbwr26yY0t3_ZTOFoB8txyWMSNNwqD>qfQzmOQ?s4ErDR^Lg z&2Oq>5>{U(bA0YV3#kc+0HZ5^D41n*Q3HOpk|~E!sgU7CJOL(+@H@vNL-JiFk-0MB zd4`olzY+e_IqmFFi~A#F3ThG+9<>j6Z?-2H6K_%h#_z7EGcK?@A4eEjB)nyH<N;_Us!ZVQxH2x|TXrYciEAf284mb%6vp7N z&@{xy-PdXzr!Wnz->jn(?~PGdSM!q~NYX58mCk_)9Wg}2zreP_HE_ZRiuzE0ghPW% zGgqGjug;o&GkL%G*7@b9Yl9e>0)})_#;&Y6E`=}>U*npFrfCu_-IkvvGDZybcK9Uq z*BCP6!DEQd_OYeL_9|D*DBeXDr?v`k_gjqu3!Z1G6L zvUq~8u*{)?e3KYD1gP}h>R>5-3S8zf9%ygpia=O~6%5yZifP z42}5io3EAm)upo4-^nuG0a}B?nY*=54iC%W{y}z)_hAHsqpB^}>Qy4{f)eL>s7UJK z1pUQODb`;xqytI(+P5M2-$y&yJ=jnGv~AU>4ClfD=Zl1^LvfjE&>E9}R{)*^+le3l z=}+Dfb+W?3z=R4?b(wr#YoYS+Rg5M43Z@~}Z_0et{4Yty_2%X2R|0g29#;+DLom`( zVhC0OqqY!Q0nx04^Hkyq5?2NyBLSt-$w4T40d|!5)%<*yz!O$0K`>k;GXyagP!4t6 zrI0d<`GrN&JkNS|wS~oorpxPyz|XBnFQ^qk=R(C{ewaI#k(Jr_01jP zc$O3CLx^1{U|Slm4e7~oQht?L;-7+>lha7~gqLyE`JhTLGg(Xc?1c&O>dKfpdG?pX zSHOu9T1V4YYg7UcBc;%7xG4uunx5$rR;J_}!Gebrf}eHRu+l-p36{KP9)f2uP`G() z{A_PF8bbz*zkd1JBOu6XTBD+f*PfrXphI&2+;W$Or-iy}YY5Wc)B{(4h69}WoI~9@hIEVOA zpv)f(>4Zl^&jvcCeuQzg6lEOj_shdi9+W@-pZ~1LB*D|#!GVKiv#n$x^=jD~B@Dv+TOqJ|wHzeY zj!WxrS=<+pC`4>9kc33~&pQ~@rGXcgc);7qdi`t@C$9UzUM8`*vmYkm9suW-T$$u@ zRtaw;bX+yM3{z1TYDS?Uyb?l~MDpjG--UDH_@|3aH7Sz}+M!E_kkmS}R92=<`V=V> z$S&PAJ>vxcnm}d0ri5`RY?j43j}g2sWnr-{qHv)@h9yl)_>z!tZ@7^9njU#ZlYr>@ zZDD@C+`o6XEG{hscRYe)Yj?Z!U?d*&=gKP&{_7(Yh2g8=qWwBl>hj@Kiu}D1PTt$D z?zQeRg}K>z()C(am?%LLobp63pw5BGh;i=EeHt6&xxKwZd8e?H6^16$^~iSHTBc?` zCom%M?u53@)w3ihPoDS_m_(N*5%D#r7g)g~{kqO3%+&~A&{|;rW3Mwo)+^>S9ql)0 z>cGU+T3y;mCOlndQwPG-ko@MIZ(ZHAm-VlN6o|yFR!N|y(QMiU(4pr=lQQ zS1BDG9wVX8l^ZKJGc2@&#Cfo@hej|cXLJ?`{S2MJPOCa@`DAdO3>zY#265CcL!Kp? zN0i&uAkJwx?DQ9Z{=bxe_wW8)`K$l%=jFY3f04~iP>FKy_DXr<{{1pPI|HKu7D(Ta zl`=g+=O3@bXfD5{yHMB3jF*$GVB?z|73jJ(7QfJLXJZYI-;{*Pj+{az}0QQu>ip(>P6@MAKCOqny~A|Clqbg)-~hH^!sj%FFy z=mp*?$ncjtttEWce^NpS)2CWCmjvIGg`1PlGYBi<_$l~h1=~s}??5q+A-HIG>t-VE zpD>M_5G(7Lg*zswZ0e;!b z4D3Of?9Vwm7WeIIhh=8^9L6$Hdfv@}W+ii2m|sFmSa+iWl_xT5KBLHjAdf_X|c6gfIknKsqGLtBHgz2R6FqC9_a6S3(crHJu~@ z;iTPmcK6GBzkEG6IXKkA0Rj6luAW!aW< zwi6su)i7dOntX$Ue28E0O9m+H$b__HBBp113OCC+4I^;K#&U{H5)}8!hV78jLm|-LtAq+=Lrh#2H`N1q(oiyg@N~+$%e3_dUU)4rV zU|ujWkISD_b0JTp{>Ay_vbf-;yE$;tTrG{MYpjHI0B6mw^P-3FK;6OZEElFPI7c)+ zy+FNsr0-B6ZGrWE5BuF73~ihKxV5ue_A`%h!1Km`WD>th^YvsBcA4smI_W62cf>dm zth!%UFL@+4h^3T_e`O3cPMyTYgh(KJ(VO=4!BH$ag!nQnc#1M8eHQ zhl74rdCd1<9FDImEkYdZP$w`5pX~@$igXy@G@a2r-S;p*H;3f5m_yZEr@pkXR92T) z%K{zi=FOYsJKy?F`RyP4cKNOE|5i3xx%=873XkbF zWo1s(i-+>F)3c+pi1si!>{OD16w*D0RtnBV?m)-r{vbnup zCVu>rcj}x(1MF8aUo8y*|4lYuPbMMhFeZo%_V_Ge2vYf-P9&31+Vc9#aR^ezyRl+i z<{CPJRF}WXJnSTu;G1p@Q`5>r{`K$5m^TPI#6;I{5}G3zM897TLOVny-rrhB8Xcy@ z#*s*5hbo=Vj&V5P8HUm3NbDu5+YV1n)A`32m&zpRT9@A3e7SMsM!9|aPPu*ePFY@A zP3N>ocF^n|c9Il^;g0MHI^(H~%T7fYi9+U6NY`3W+pbi6!y|+v@2OFxsYI>cjd5v| zYO5bHx^M0Mc~jG>Orky~XWNHTEA0j5QV2{PM(j+Ogz@~*y-d4nhD$$OpS8gSyerX_ z@meRt`L6ave296?sm|GWJc$SMS(dhp)QQ^Ru@kd{^6m!@%KDDOO;cgIGTD{ZZEKY?C2^0&sGILuPMXcJX4X!lpx?gLMq9l$VnR$~!fPT)HC;2Bg33nFARhH1z6WrUO2 zta(IvJlJr6hLm&2$WNl}&i)y++xaCV`MF-;*9W)NupDkXIy#_Cmf-}!XM$(SMx8TM z3*1jnf#aC_FBGKkv+5MXTIwEWth6#a+el49!NvEnv1t_KnY82NglWjw$Izr@f~D;5 z@0880jq=GSAC~Q%&AbmYqzi)^?5at;bD>Fmbt7_pc~hJFn`^!fOd_H)1lwPb zI~^!-uw8(9786n=2&?Ac#Bv+wmH{}dQHM6Pc0ALDrOHGHY z>gp1|IB|HGiRazjom|ec@$5-?@8>_uv&3^79O+-wRI0ApAe6o=VWa%j(BpwnuiKv?tJ#NLj zLJm)W@m@bnVsp2TCLtTM&C$Xn{4j8tKrCs=9FEl{yxZJxz%SYq1%@Qzid!^^gdd4p z;#ub{DGMLOEAha3IC0&Zb*D5^c-pKJCXycirbRf*q6RS)NnI_V-lpe}*NwFs)M>Kp z?;^15!Q_J9!U*_SHlCdSa`%3Q>;h=YJqf%Z=$=%3OxYdppKvK{&$}&DbbTS8JdF&4|nH-+UpW%dsn@_j5H_(2bl&4Q0A^;3XPX=c@d3IL6X%ZwZ zEWWb&YKaK;Z?gGKGYKd8VmjxNI0P+fM*(?ilrA-}B@({`9;9^mDd)t9dHfUF?pg^_ ztc<{p3hLWY=N_kHfus>locO`C1Pr7*h-gmZxsgTcYxZInZIp zr|C4rPe+>SU97J0QX4yOm9#rR;tI)Tgng(U%CmrSDN zA#>naf+u06?)u?LE?paSM&>W9lCJ+F>0jbOHA>6vdnLG*#}C#)Y19`PLX}LjRMKJ) zR@Wmi-0yFuHzQS-YkZKTo#Oc75c;xAyb4?Ol zrFAulJGbr@RwW6Gvx=a_X@|H5LKoLfY5n8`N}I?PgU zhqPpt!6PZNjI#$#~qzeCp{?k(1BD z&-QTms%kmZpT6ayj^krt4U+|i;xf>oJ{5nw?)GrFU$!=%p-DU~2L~I}4IBfG!Kb2@ zb6A;#b^Xib!PNy3pyGl^^a-9=J_-)^6#9$ zGN#6~+3i5O=V}XjifN?b9)#kY1f4l!|8`dVRpYZPwIkRPtPmDmPW?J>T`P7V~ zdE|rnD=7^l@qvF38z<&ao;`X%$sW79xIi3Fqdkmf&_|8lZcQKR@xq#HC(7`B{^8BF|_{)+P1f9oL=gq1X^slT2Ch zPkH=r1;R8uFpUt3?pxBfZFtwq5<1V2&2o5~e4Qh3tv-4BOulLoTBY`S8fv{HNG9RQ zuOEE)VcFi@OS&4F#2FH+xK%eW)_Mv}ms+~y(l=Yl{FAXJc!idLrjofQB=ZP5_?c!M zMv{q45{7m@KPH^db(K$RH=QQ=>t>0o>CnzHbnmKg6JU?@-9sR*3=fCp=*XkYA(|vM z1#Wm)WcDmjJ_)kVo+iAqwo-1~zFS^<``cyd#;r1o2I~QpGL^;U)eJ+;EzDisgCV{L z@9UMOIb9gHH{*~J<)fLE2ablGOl)0Y#FOHzoB5{0{m|Sjtm#r{ajr6nbUJ$#;o8J+ zCTEQRW}XLGMW9NI(-}dS3_TGyk{O*Wli4x}-|12<8$0+#xjNst-6p3ToaPck@=$xo zvOOds1uXYNs6|9NrISt1PNR9$D=;Nw4r?qRtyvcdh2hOXhUR>RcLq$*fkN0MXvA^J z?erYdCjk%9FsA3w93VE0Y1m<95_aYpY|ar9K7eWvRm&^_cl+ccd#w zJQY@=rHw!VG#ishxr7G=bGfSf5$3>&s;xq30TT2-+Oxw;G7`u3+b-%>f0<&tRWVDz zaqC?t#<#7-ylEOP0))0#4=sV*WAxq!m@_$`y}4y6JN8K)Y6XJ2{ht$Yf8 zMOrsgMruIW2Ib%o#(?y{v-=F@yq=@I-OX+J4u?*n6Q=L+_SDl!Z|B_7zA!*Egrnnr z8PE@%gXj--V2XRda7e%OPL4W%BcphZNu*)ElBo^zBJ;BJFTQk1w6MC(jw1eV!lZ+} z#5OhgMfO!jq&L`$f?lTe*|JEm^dD`4&oBu(1)+FT3ga214?!{@9c>7**n{g?OolNe z(FkMNvNRP5%FdoMnds2kN^E#`;M8^^e9~2lvuwn5NW*a6Qy~&&jF+&EiAoG+XQsb|%TY<(04qGyE*O#73f*pu#Hk)KYJ)e|W|p zYg}R)xPzHQu#1OnLmN@~F=-?Gt*`$4#NRYbH~TP1v&}OpQ6~@L7(Vc^J@B)hZBK-L zni|)k8Qa0TG`cd9Zw(TUJgZ6Qs-1c4gzY1N?9I(3PF6e(hGlDOw|w~F2U*#ZiC2qE z!on$g4rI?JgtfggtO2l`>YAs5f%q~_eHA_y)MkhnA%)`GhK3Km zk+1Eh)NUPwh4|#{h2oY&OA=y@$HQ1R>qs$x$!Q(-fk_%p;_gytkK{0nWj3uIf{1ex z`w(X59VD(YEb~^Y3FE<4V;G>Z3DJQB|C*EoY2 z9A#;-Ld?`G`OVJ|rjG{jq-^axirw6Piq>#Y_R+o%4){ht+S&E6z+=ig8%8zTn+7<- z#1&V2r0xA52Wad2vHSf^peY_y*hjblKd&%}?%_+Du2sK;F=jgEOOgcU(P|+3}w(MoV2ntU!MNTI~~SO zS@#Rr`E>o(Nzh$3mP!0Fk4!N7AsM#-ouqg%j&C}Yh0d(H+=tkxE_+LvDm~O8gx>?z z?0DYo5TZif4xcGW+W8$z&)GC|SSOxy2%7}Kp(AXrHBDL$NqEX-C`z=cEMr81vs_vw z=B~7tS}x^F-S|+6b`8;1&s3sswQB@I*6{5;K*>}6z3{JLOsBf>4s63TsB7+BPJY7M zGC~jqVd8XYwF0;JnD~>RM6=aRTjSM$wWgHc`hg3OQW&|uxWLp?R$YZ-Jl%}dlfT-X za}w6u<1fa}CrTe8`0;~BWy6bij?c@1V^FkPw2HJ5u!UGxjG;_jIXvz?rO10%ZsCbh z6LHddQcD{;cV*Mb7~mM$bK~%nMBfX6WC+47cUge5GFus>LWk)#I9IVwg2*#?;V`ER z$ayW}dI?k2CQI=)J}2vQya?Z;O`$!>Tu+W+HWFjBn9ReZSamg*Rq)wxuF|sa*mkqM zxw5jn9ASnmD1~)&qZ@=ASg2jOV#(E1UhV4r8)_n^&wm$#D5};`dm2O*d8A4q-q*SPsoRAADn~x)e0j%Kub8xRUWkVq(nOqe7)zo?FpgA=L?(jw z78Wuj)Z;mXswYN5Ul`Q<9aT1Qv!h_;v3WF7Z=_iaE~9v|us7Hj*$l%YgL~ z-sWwYYoL@NmbbWFy_$d817n#}ZjAm_TIZVrfNgA8|Zp z!sVo<>CoWmu~(2DmJdF8Sk`wAO8mlTwxWQ z;XUvq&pPiw-oX>{!&^UvmpWf#dKE@$Cr1wL?C(eT@W^}T-kf6~FgetH9&@vEWqD~C zjbVE@(LT?&MhMwH%#I?n?6T6zkj_tgM!%XSq5<(dQ;VpHsL?xR`TB7c`_*#rsQK8 zBJq)jyJ2mULPL-0{j-TOEYoFw=xQ6JeM=u^0AUoO zT^%S0|8D0S?V(3#5B0(&?1G)q6HU0I0Q8hqta|_ZFhJLLs4TSp7nL|*>jpC z*1nr(;9wJqpGGEGH*+d*q*$aY?oxsf@XW~&M|_I*V;u7mMo9b~<1G{0S1La^$Z_>K zpb||=;ljC+WrvtnZ)B*PK*H{1<~ z4s#BpI6>3#h#DBg_)J+?S}m)qcX8Ls6nWdu9=l>#HHdAP!_M}zvg^_1gMHf6eJ=_E z^dr}=kWMalqV4}9llTJWRr$ZFbYC_8Wq?YEG#BoO9Ze`O9eHo&s&~i~9bg>9ltCy# zgjhu?5|RYMSbPZ)($$gp5GZ4) z;}DM$U8|oA10CIkTMb89cqwBrz{c;n8CEmS0N&Gn8`6@{P|WHggI5s z!QrZ`wxJMqd$lV&X(OceT>l!J!t)ZY^WeMR>hJ{}%ZbNswUK#PFWaXBP2kWy#XnDR z2}`2R>123G27z1WD1bH335Q!vEr6-%Ux)kfqx`;y&~?VTkYe|CX$;qFSKAN<%V;(! z2Y#bW!tYMl8s52x`Gqzg0pmDU+C`H zL^z3=jGf}8ZDs1_lT0tlC1IB6!6c}YI5;h{r`^2O&C98T-VE^_hS}|Vo)-iiVp+9Z zzp7CvjeE=sc!Iw~U+d71f8vFhp=K&$N*pRKK00g@27xcZ;%|DV4(HfDme+i2gE5Ho zpnowe>j|$1d%NY}U{DVGeYBscvbt7J0uW|>!Vb_*WMUql-$w)KA0I;O`@jb#;=G2# zyq1V2jTVWii%THt;E5YxeGc=sT&`q78|lq0m4*2mS-fGJ)^twF?(Vbl?CGavee)q@ z+lmIE_K^7;p+R3)^PBjWrf%`5X4<6mN475|mB zy9n^rnM4f!m!IvJwfxyp4dU1 zT*-_C*|$~#q)hxX93gR^hR8tdvs2V`uythzpCS4^q`n1+)a>kZ2#2dNJZ*H+327uJ zm$)i9W^RJcnV}^K4P~}m8Pm4YnJ0Cq{LG$+gSCtoCDV^M9eCnr;Umf8$~=UH9kG5i zIN@a}xXoNXU&5$Lku~AUAb2({I{d}F5Z@$}b)ST$h96-C`8CI+i*4z~=IcoQxISN$ zK}$IEkMzyE&u3>67s~=sM=Ea2!sWpWi>~1D++GMH1WMF6I+DMsYTMh z3N;gi-0u$v3&VoQsWluS!PlXo+TMYm@agScD3KU_kLx+g!l5Qulr?94D8XhF*P~8~_cmQ)a zI6lbyz@TFk9@o*BgZWur=Lu_{tp4^+u(%R#!otHR`gkK4T)0HWn<>uWT<8}W?C6Jot;u+&tiBkwx=b0pk zZ{cN{-iP2{5|8cD%X62ek@D=DjMBK(8d_p#`jtpm%|dc{l}RMYi$d1;maM*Ed9P{M zR)i%&CA{_fX!}H>wjP+|Lx39BZxTg^G2AUJu{ndtO@&E#2ScQ7n1mCy9?NksJTD(U z+l}UMJbMFXu~KGN@08i4TV>W$Oy`Z~SiBeg%x3sV0%bbx3U-;QZJ2YDFpWvLmnJPl zrH>)1w)qV09Lb+D?eF*N$x{d!RbwM&>LqNfmq%Mv_+{f`fLE>g2i8dUw($jy21WuJ zm|%0LpNZ)wkOFi6c!o(F4-a^*!(%3&c|Tk=UGd-HP#J=&^eVHRjGuD|WfC|~oRp&i z(|}P7Pn;i6lc;Tz4UVQqIi|*^G6^oMQo>YljQXFK>Djrmx_Y~;t=y%5tl~qx(cE0@ z@$~6~vcB=KY;Qe=LG+0!?9@KcOsKblNr6F(kI|o8GOGoi^*#wQw+v=Tc3;}9PhZ|x zhL@R9#Qsf~SLJ`%X|Ff0jNiG>89YUKzf~)t5+{Pj;znFESE6kzhMJ#kTi-uxo5?dj zx#Xs+gq`KY<$xJCbz>bJ1!*#52BZyfgfNPrO5~0FSjXq;DRJg&Yg@Wx2$<$Ho|H7N zgo60Hfho*@4xj|*@PSpaQ%Df%L2jPoKUvq$>ArXGjY(vq zAr0!EWlN_e?M58a7J+9M@51_LKGcD9g+tglX=+<}8k1jNUm2>Z)XJi%1Y9wjS3$L^5|JkozGj0X;2yE-fV!m!P^c z+l!7UD$GqSM~2~Wl6V+MQBPrE{X2ZbN-Sjro+%~67h{CJ!)VSQWH^lXz?1SOnlQow z8ki^LmdTRF;o&eF@=QA?3(%G~R@Tbi-d@?*SWlR_xrMa1_4YoGshnY`hEi8$3G1xc zj%1JPP!f4x+`dN%Ge04&@cjg)Ilp|f+`aRia_8RLWpVKq@h8K?kB^7s`?&09h-oi1 z^VoKe;Bd8;c{+mN(f2ZlN!rA@jqx!U_rLkcJMRdpbS$%di7O_GfG=`!UTzKZGAmH7 zn1oj`5?OP3kxlOjW=Kr%G zgV!iDXukWcey8vhFbgc92*e*-}>hH1DhEe5J z)(gxel5_&gMW9-bmL?g5IPomu6IzzcPUc5lCoGj-h)UQ=5EN-pgd$B>!cP)@LYSL} z&-^&aory@o+ALmfGdbm62|fbY)Ksa6XUk~3dM*{64}zy8m(EQgg_;wD4pZPsS(K*8 zpE6Ww&@}9zt+i=q;2>j2`$$mmcI8QMSVGQw2tFCNHu76-JAMR0)F|I7)2Vkd*Ogli zd$b`1VcU+(wjRxNm_#1HP^Kz@$`>;+Z^BDVEVq`-EkkAS#?-CW*E$E~5Xo8HEXF4p z_94Wxf9MY0LFNWLhTUsEEnn^(r+oH>Lm0vl;he1XWKl2I+1^~wu@5=TmwXqN7R&fd zuWTJ0mZOQ8vi91y%kurVVHT^j`&1e956W(TuT1wQOK*O%3U=VY94 zJ=$ExLpf=K!SP`^mf!)M3O9H%+^EMwIza zOfHs*KmPGM?+8$h@O!CSofm%prkgKPjmES_nU^d=GwSyu=5{r{zl|YONLRvAzlwnp zI*=lgWc9aWUc{*ZX^Z-;x_KfTuK(nvkMZ(w)u1w)S0&&)Aw8WqUP=!LaZ{3(!03Xo z;}SVKL1pgv875_^iD!<&ggSqTx#h7_87DhIV|2S`%W4ul#uBc5l|Y5?lD?9ZL_lr9 zBM{sJ;i`~CCJl>J4=%j45-FKL2qj)-AX$urOr6w9lmu(ed^3&Yg+I1N@udQPJ{0kX-Hsj9R<`>c6MnZ6<45l z*5^x`()#Eh?|Rp^@-r_rM2uk^Rx*6X%MlEYAgoH(j%h2^x>sO!ZZ=1==jaRKTd(mB zt{z6`MC|rXC4>&ASa&z6NfaMFeUc4d9;~;tx(3|G%cEx-Wgo`kZsKJ$jAfX?7{qT6 zVs?nc>#*Y7%v9;aR3K{<8R$X0!x$qq!JH+mh3v4eU+U zpJ&?>SE1dx0f%VB+^}fsoufk(3UHmPkhz;r@W}iqlg|kH@i&jiYouzw$=Or*Sr)Zl zPY!UOj`K1(&IHZq5Ez}G9R%OKlxrNKe{wR0KMarj)THfyUePLF09|SuIu7jlP?Nnf zHnm!MFpAZcdoTy!2%*mfTI4UA+uhlOiSNO)oJ6ltPheaMPR{Mni*gPY2~i*3#^=!b zR?sA15>}_0OQiW1t#Wqwk~7SIyP<{)*yll2$94R>M~bZo)Rpw>=P!HOcs{LkENSXzHqygyLC3Q{RN2*`_@C!x$gyb2@rwl&ZrhB<#2{5LdV)O^R71 zN(o1;k3_*0DLI3PPG=auMVo*L)=5-|B5@pAaiUfNX;HJJ)Sg)jN*B_!(j0?k7y`t+GmcwR3}%ZDz47E#HJm{K>D5 zNi?MVrkXEO`l}sLBO)|2>hJSa*j$a@zK({v$|%~nc{O}9!;XTa>kz&U57OLz(hY&s zm7e+i`Ep(u{G60DjY?E&(is<}gJeh{NW?qOP}UF*5jRYNzy?i8Lab_meMm52I=sh*!PhKV+Skr+7Kba~W-#d2a@$A=o+=qhD} zXwXp|zS0;z#K>m=<#?||LD&dCo>GSFKsQt2M4ZeSxVspFnx5GakklO4KM9uUXE=-e z10>T(5aFAr8s0n_qapta!x~o8@@~fOjY+ikX4+HpN?c5hgD3B{vygS3NX@}3PHisB zti&tRbj8ln@)E>-Ca~5z4da|ZJq*vIBo52&{(jPPm_wrGn73o#2fMpyYvR{=IqdJ3 z{oU>26}1kbIEn4KPiluZZrwoIhB5T_@Y@0Z(DG;}lAtceuXU*h(Af?$H;5i(7k5XX zRN0;CY``W4MFhGX-re$qM1M|aKt67+KEg@0&d!MxY9N> zoNzn|j#s+mpvPY9~6RG!{q+Ohs@t{4m2iCox0#r)NX> zg`lw;6LIISWp)T>79ud~b&U`>S4#yNbP9_Ho1oLdBt>8;f*vy-YMLV1Z$J?Y%F4pQpo zZJ1Fb?1gW`!P?Ro;y3GiWePQsQ3laWWqSBSMAe>hz$5-j*naak3eO!{Tw2U!{|?Kk zwK*RlgS385j(WzC%*0EioP+SV$$RV8 z&9Vn!+Z_yZ@ZD>#-=~cy%cD;pmYuDwvP8bljalqK51?Eww9wVx;h_pkk7_Z#)*$*j z#=_lt^Gw~E%GN5oXXwE&D#5`qKE))OiM{NnL2qlPWCBBRqMZ9mK`68unbsep< zkI%n9|J*vL=DPSVGF`|Z=cSR%T&5=xR!ayOZQ;TobgT0!BayCgOdDK*Xh;_&RA&$c zF+C^1O8Dq>62vx+?!PL3Emg%O>tj7Tr}Y2M1Wx9UtEA=* z)|~j+5pv7yyg&#Z+1RPQOMA-i{CO1m{^m~U@9md^y?)#wQroaUC`W@Mq^<+%NXLQL zkr4GH4a(^;Wal%8%JV7G@P0WO9+X+?*qa_Na}dN8G=s&tnQ}7NE9*}l zmHnNqNcJ9V=lso+XPf25{kO9r&Pnf^H*b_Xx7Nzu_IBBL@-*$4p*m{~yu_4>Aimc} zs$u0)CJFYXrm4RlX*=4`w4x!}R+Pc|yRX7vrXSo5BN6{4{$?N}IfFop18NwyPsP?O z&$aCdFJpCCuWc#gsNsoD64_5;c`2eBAl(Eg0bn%{`WR9j_mq>A_^@ zs0Vz^`>)SV`{YBvOG!=C`f%OaE}I4EkHN z=N`<~t7khc16&t?;=<`TX{Wv(SU3xV@-*hTGVw3}zStnZ(-scD7ewN}7h z=l^+a&Eq#?+vDdo!fMpLYDWFr^JquCF1|#56yBF#ssW#Bhv?qxQ?*Lq(ImQe-O;qP zn(NYS#df|ETnL_R9A9 zb{QNT@J=VBgPsgekh)+L2Sfb#OMiE#4EFZQ!EV0{_7AXq7|3BZL!Ba()g{5yo#(&+ zs_5PYCF)ZMfJb~B6J|K@=mVG!&mr`bO+F?8^}!<}G7n+(vAQ8xlr;n$IJF6H+oBCO z8LpY&(#U(oBg0pKUTAHm*IDz(vq5X7fw4nrY7j?6cT8NKWL#IaIRWjNQgcZ6E6YoK zAP@nlPKc*NJtx8-@#>ITe}4x_7L5S{H8(w0W+6U3o+prAZ{Jug^RrVq7T%RUwxdMU zlTJ$yCe&Mkm<~w&th|2zwP<#m>+6Ky3o*99)PO(h2b_G0H$+_Ri^>7X)YUTbf%L%_ zG7&}|*&^Vqb7KBo8PNuuU zYkU%IV`dTNy$n9Wa8JjJ_q_MqWI8>OJ1Qoo#8)p-+9szV`GJ?O{?pR>U`bzAV_Df z`|i_d5iY+}llH+}_1AZlnof;ve!8Pp)53)4(=BFsYU zk|>2a_$a9-J?dn&>?*pgiWf}6r@V?dk( ztnm-FcVRAvFcTTaAWX(%7fuL!?6ObZcXoDA>vziz1kmd*9iMmN*Rl#&>uei(2%Q90 zB2|kHaq@%UBv54%5WJ2_G`wtZY(`jBSXUUOx9e|4al7<7Yq)%Cak_WgMS)T+qNN#P zPd&Z2!2JlGJEYX_JcLBgJrWXa!^M)UX}GiZV1GNqN^?_a5=z;pNX(~)Wnm7@j(X0| z&6efG#o*f3=0+GsfuZkg_sg9(-vUN1*W4{{y#89bxpuRxKU*(Po;)Kogi$#1L^Fdg zx-bVBZkf#RiLlH>G-=d11kd^Maw-G{@x|duTr~+b1tonMb6(Ys%}Iu8lgRjF z3L*&pHW~2A6`#~wO)(SV*c+5p0mg~{oVi5;GSQp@3qkfsb1xYZ31-oP&0pqp0Hg52 ztm&~C-od5QVL3cKD2FGzWC_EZ#Eu=(4lomVoaM^A+ZlD4m@6~0%hYQThOk;@rafJD zu`Djmhe6EtU>ei(%ZVZRtdkBnPTxJHO-`Ig>gFV5@*bg2p-A5&#pyq25;L>&W#Yg6 zH-Gw$04HQcPAU~d(yMa?ibgKlkn1}8O*gM%64%v#)I=q2miMa=Y2QZEkv8BYux{S# zYfSSaN`!R@cJ((8i876=wNr?c{Mj+Ic0$V}=@ofL)78(eWf%#JY2}?4rSeGvnn%*Y zot`9y5|L}tA%5aZCV@?iXNj6=}>6n-OZgc^v117@@K`F29H>tLK;gsPKZkyhr0)5``HHZBmgi2I>Xc$ z1e$MZ2aa(&q=Y<%i^L}LGfgxMnafz7kuqTz`@8$)5Y6IXoBX%7%ibn7?pE2SO#3^# zWpih<{MBFoW%BB#PgR zBg}9wtccMJ2^a)`K)ispad}UWn8{&$Ghcxf-=J_c6J{VRW0>^autaGB55v=mdjLE%kt9AoYk}ngIHajgb6t* zKS93&clS5S-u|<4aIj6?U5@M>8s0VGJQDpK2AvC##JllnU@$=#$~@I8t7~`4#6SPh zpJp?iph$-YD@PGAURT_|kERmJmz!7B|BHg>60Tj|l!5=0MUS{X@~pgEzgE)-@N4~PC?Ab*Nt#~TUhLsr6q_Fsyp!-U7Csn;T!-0d>)&s+i6$*U1zevZtSGPX@eYBe9zQ}wY zCK0L6=WDFJ*FGi@^u4*2z}D}|F3J>&m3|i)6SfB6x!U;iA??+y(QvbhgYULkGy?Mo z5%GKV*ZQu>#<;vx=8+E~Gm_8wiI=nU?l?NqrAzUwqm02YS+`DG7 zg_d`5Bog{pzuZ^>;Zln@fY47vyl&oH%P>iX7;Q@mW0Glf^C8bj?Pn4;BzE9*1OXSm z?pOA*pjilWCU=P_zL=kgtMuwI-#y^wIb8b#1%dVAHMh5J-YR>$1El2T^6ek|4jRTp z*`ttWFqWZ04pOf6n0ybFdnk^F=TVdpJ6A1bN4{+h;mww%h1GKV z&OJ4WpS)wM+wk(%5TRfJWr=^a?fvhw2_yUp7XE&%f3qToZZo6Lno7VsB5r?8yslG% zXi-U_&|wVre=&jfYQ}I927{*^ed-W8Hpqzy_S3U`x5G&QPEmy+42bAq4rdSwCBh*c zUQHreh8=|GQ^(^Sa)N+|(OFLOAN_iIoIEDUhFJ{BST!osdb>9 ze9x(&eUEiM$k0@Ok7wM0a}Y|m#2p^e$s=`D2~eVuUD5n0!A>Fh{=@&xAC}+whreIG z4}(~|c_Wgf^>>o;2m<49Pc(=~wxrP!ZyU}tb4)M(g2c3eiSUfz5hUPY#F+P`p}h$o z*xKZ_iDeC<)O?yIAqeWb!Fi`$Wi4Pt8NhrGVW<{jamgLfi!f`Cy8u5rCShJ7_&z1R zX^w?pXBjMn$ss41maCy=U=&UqJLFSi6PNg|8k6WMtuiscSSBFCQwzAWy)xxxRLiTS=Mv2+cPQ6uO)Z{Bam@C5z}Y<-RU6ABy9Als z{Zq1cxvmV(exhU_O}J}YXm-k)#z0uXD{!hrUc9$I%9y4yWTfWf9uJAJm-`q#OoH!f zjHanpT#dAVw7|ohn?zZhPYZ_=#%|dm==c=44&4S!6afaq_rUJlL!Nr1xlm^3ZkDCx zdoc1fG`=OurSOsFC%N$qd3h0%%Z#n>0x(=%UMq`>YcQl0aMvR{Jk6In%3Z)i3os8{ zZ{50E?%r-pBE^25Ni>^pSKPm^rgqO4n^)DpcEwkl=V99{2tfie2|Kn(Ch|ryPrKMb z%^|4E$Ifly{|6Q@gWGrb+`v?O_?oX?q!fV@se(6`S?y~Tp5H#HXwfbYmwv}=BiTL z7)X3Zr<;XnAbn9*rS(0u16L-gF~}IEfPoX%lS)3+SDX9^KT9X|JbyKbFb4>{W7{XV z(-4VcT#tix?Ac9RL*SrvwZFSlcF{bx(F*nt+E^{b07{XuYncEY{^qTE0n+lS#HsF@ zorh@Mym`Caew_~Wtv3K?K$ySF@-3ygnP?~j^75#TdVGk(4iX?cF>cz@_972DrucBN zSxeXmCt#C91$nMGL+H51!{7+VY9QQ%(+zXs$#Hb^ks#ME)rd`ED>2Lp;tu?Y3;4_K zffvvmhdHdQEYZHSAPmmpO5!54m`2*UmZK6*kN>s~pj!uDQJ`*K1BOsKn?I5~jH9iD z6n`9onw^~}i#;?B{GL8~3jZH3({pQR5WUh{yIq#$ZGB(r8vE$2p zTf1==hPIM9GV#s!lOPHv3AJ+|J($n{JdbKX!6eKM|EaARQ0DB=RCYmQD z>PQ@7W6zV9Lss*%vt=Q3E3@DeIEC=!kW!Yu^4)Y5deoGte%Eb*oPftl_;sV5qe%|v zYkPzJ(jU?fVa%|P^bgz6yB(DB&tVW#lS>f!JC#8!-XV|q)YV}&{;5}`=FZc2Tb=i2 zdy?|aTldP{JFk@+H}0YR+@M^ZnKj2Z$|tP=7iUQ8=GvX|=4)@4`*&ZfOhTly&E)*L znud%GAukZ~@3E0MkJkIMHu&^HD}rC=e`%jjCybzTqdicD)_G#YD3MrVK?A0%=N+U0 zVRP4mW2AKI4E=~5_(S1x&dWKH_&JE1bMn1%GM(2YormxWq`i!-56TgQaR^fwY;7V< zBen0MGVg4cO;rDl^`}|2bFjZ(?!EPPdi8|)n{a}fV2Ph1F* zWu!w?>60`F66s8WNEi=R^N>CzbypENLF|O^F$}^wPt!iOkqp94hD;vqAWLD1@A`D> za&$1La|db)XaNpeEg^Y2_Uo?btH*HpiDUx2{Kum@?#{A8?}O6qZ28r^#}Fl>IaI;VPoOCnfuPP#xX-|B&N$tLj6 zQ6#kG0LgX;eAJ9QB4ciD7Tl?4`?%A$3M`}_qGbZ6M_DZ|X&#?UkRDhd>}8OAbH{av zrOb-FB$(b5Xlb&fn(}$XhD$rA#!t%}@Z8uyI5{{jy%jGlS}Z5C%jM3uzF!`0ZkI>2 z-H>A3yn7E~-YbuvY|sxT%D3PCR=Ick7G)pLQQQg_;$H3>fhoCfAoFg(PVfm2hrMb$ zP*U7z6IwKO>*w%Xo3n_KJ_6FZb9+3O9_8|@*%=t!B+O|Tf-ZA0Eg6vMI`1-%P?2L} z$UMT0OoV)7zS)J%`y2vN?wA1P$CMpVqTM0vkcQxPEG z<+b~75OxhF;n_`;Kms+YNoX#KT7CcfZY0z%Gp_=JFnpOYzBYaLnrAy;C})g4xH1AI zlV;uUm2-x$c0?sMrFwT)x=d9+S5dg8-}hrxf0%(x!EyN^lCygSoLqA#=U^Y{nGQAB z-zhuKo|fIs&77~Zx3^oiAkr>TltCzQfA@{oL25`59b(eXLp~DkbTd0!I(@A}WfCDF zyxJKrnS?}7f>D_Rmb9dUuFn>VY7JXkTXi0SGD>vXP?JkkWg5{ei0inyOIyuff+mr4 z-obAUk4+Fq<}F-Y>n~IEOrUKTqRS7R$aKtoVR5;vsVS`9D62PahBJrlJVp)FeR(8@>?L!U1F#|`pym$CG+JvwQT(lX}P&klm zR6>>h)`f|bi>s7bO??Oqb^S{?aYiBw_=UHr1*s}iQcJ68L%0mjdsgoN8<|6J2Ld#} zm8rSj-({-GD>;o;A}&mmDS7E{E}d)J$s~>-NV2LE2(sFQZJw2KGyqvvV`E?}hh>A7 z;*!eg5iyU;BJeEZvt@l7ZD4$rY@yC zh+nncMlUVl-65^k;Icy*hRkGtd#Cha3R(A$btuN67SGgiBiY{8Mm9Jdpj9~M&>s*6 zq;tIAaww^Jw=h^$#>m4?=o<4ne1hcVP*x_t{jUU0CPAU8lS~5FY7)mz8pa{vHx%!7 z8kvEIx$SOKj@|vL4LG5D;$$;Y7R*8a12hKxBK?^w<&jw|(+L(JCLT55k{#pj?d+GQ z51)j-9V3R0PfXKUmdmZ%_sSjA>9t#T%lyh}nP0nE=9ZAK>_~JLPnSKVV#sBv{={<` zBaH6w1X$DPb9CZ0G>Em^5UjN&vOCETlM~g=mC5u%Yz91JY9yaPFrO zV>Nr3pLpY#x^=8@YgS?>e8m-yop#-s>ElJ3VG1V2OTv?p6O>u@N*FiJIjolZ5@;Kj zZ7wX%mgS|n5N|hJIs92SqMbr$#Lg~n(@om-Stc~J}7t89s*US9sYVq=){e1)o@M9Im z{@w3>znnlI|MG8s8m4~(ZSJ)<-_8(WG+=}w`;2+Y=p@=|PIdBJrh!(2zqOFD*k)dN zE6vNsLi-`c_b>?wJT^mQFpC+8{S@5U6ch}y>)N!0f&CI(NF0R`=PiJtT14H0WV6@w z!!XV#seiBBx__tKd;K*8kA*S-*LDu}%5EQF3C&}Ab^!)~0JDf@I|~t?nFp_6Qnb(U z(SC-B?f1EJg}y3m(T9@9JpDrEc8q4RNB?)jC)uVQrl!C*nDmTuM7(E`KlpS~CjQl* z{^T7I)5ep@^B91P+P^DvHQ%fDRVEXBxSz+?;T`Kt!>$5Wz}D2Omh>VBByHB4TZ3ws%Wj6|Xaq3{$>f)GU*yQ+q?(r?Kt@IA>m zyg6rhi*GWANWn4*$^{J%Ll~aI9DGKTIVQUSaC3-bWn~5-z+pSe13&Y=0dFe|hLVR3 zC#Ggzg*-CfK@->Iy0RywY06EzQmnMGJJT)W{H%h-FxrCaeN?hcFHF=v=&&Kehg$25 z!+xZ{y^RnvgmA6Eyw`4(F<^NAwY%jmnwy&MAp(py-AydqDCZE*kDoj)yWr$0@qgzJ z{s6q3FYmqkE@i6=FNB3dL0~@Cfsz z#f9Lp?d!8kdfk-fm8x!DlM2}01ggw|`l)HmQZE^x;y`u70A%sJWV6d(YfW-YTQGH1*jeo2?$zsU5AsSnghtQET_B zw{YPPB7!aHY!Ydig-BK}-T?t21}7d}5TZalkiQa_+L^NoiFa2vWT;5u2BUBS+I8GA zgzc>@B=Q~7ao9@Dq;3Gp5ETT&blexAMxhoW(f7ECmHA#-x_yUyEeD;C4&)}Mj4~4@ z7ZAnPIvK9Iyu(<-45&+mg+%5IbsDvvayhi*`g|FK5~>^J_V)J6#-{Tl4t?!_yb^ut z3J~pBcJ4(a|5daAcgA}0yUY8aD5%#f<=)-b%k8`O%Ib~VWoh|FS-EkuEJ1L3Xb#?r zHeu&P&8G*!AfQ}y&~Ya&k;1%V+q<&IVH9@UvvG(s3}F&VIy*lFvmm_0&W#k-jk?kT zR8{LFr!CF5yz>n=f&tGGP+_58#R+f;Vjf07yJu)FnuFi4Bqh_}x9h8B*`*tJ(;nF1 zGlWf-PojjpDpGOPBqZc@l3IA>#yN{f8RloH{-g{-!HGzg-5Oa2s9Bxkz>9QRze$}s z>jnC*&6i=gVJ≦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 FV1h{`q;miO literal 0 HcmV?d00001 diff --git a/share/qtcreator/examples/15-Utils/dict.txt b/share/qtcreator/examples/15-Utils/dict.txt new file mode 100755 index 00000000000..f43275c9b26 --- /dev/null +++ b/share/qtcreator/examples/15-Utils/dict.txt @@ -0,0 +1,6549 @@ +光 +环 +主 +营 +: +热 +干 +面 +原 +汤 +创 +亿 +8 +1 +0 +香 +花 +桥 +社 +区 +( +街 +道 +) +藍 +色 +经 +典 +承 +接 +国 +内 +外 +针 +梭 +织 +订 +单 +欢 +迎 +来 +料 +加 +工 +P +H +O +E +N +I +X +T +A +电 +话 +3 +6 +4 +9 +5 +B +7 +申 +滨 +路 +爱 +拓 +升 +密 +斯 +全 +屋 +售 +票 +对 +讲 +机 +元 +茶 +刷 +、 +纸 +巾 +无 +限 +极 +安 +得 +装 +饰 +九 +龙 +休 +闲 +足 +浴 +中 +心 +凭 +身 +份 +证 +领 +手 +信 +用 +能 +当 +现 +金 +人 +民 +财 +产 +保 +险 +股 +有 +公 +司 +美 +食 +餐 +厅 +厨 +卫 +韵 +达 +灯 +箱 +裙 +楼 +助 +教 +聚 +时 +地 +线 +2 +- +同 +乐 +坊 +l +n +t +h +e +a +m +o +f +v +秀 +沃 +尔 +玛 +帮 +万 +家 +企 +包 +宁 +波 +埃 +柯 +铜 +阀 +门 +联 +系 +车 +养 +护 +站 +方 +時 +空 +購 +物 +小 +牛 +肉 +萬 +事 +興 +奢 +缇 +郭 +氏 +生 +堂 +, +支 +付 +宝 +和 +微 +都 +可 +集 +团 +纺 +品 +销 +棉 +被 +您 +! +碧 +水 +缘 +座 +椅 +定 +制 +. +脚 +垫 +临 +富 +园 +烟 +酒 +业 +幼 +儿 +拼 +音 +寒 +暑 +假 +贺 +佳 +节 +福 +官 +学 +育 +世 +红 +璞 +男 +鞋 +始 +于 +C +点 +粥 +粉 +饭 +类 +满 +送 +板 +栗 +入 +太 +仓 +市 +优 +特 +利 +贸 +易 +麻 +木 +前 +列 +腺 +一 +果 +蜜 +婆 +嘉 +际 +大 +店 +洋 +河 +架 +丰 +鑫 +壁 +软 +背 +神 +童 +文 +具 +梦 +之 +星 +英 +语 +铁 +客 +代 +博 +技 +笑 +甲 +山 +豆 +剪 +发 +想 +成 +行 +旺 +明 +吉 +逸 +夫 +程 +館 +酸 +辣 +盲 +按 +摩 +疗 +祝 +健 +康 +泰 +兴 +场 +监 +督 +管 +理 +局 +城 +分 +间 +室 +所 +域 +冠 +京 +丽 +华 +便 +活 +动 +价 +。 +详 +情 +苑 +村 +南 +烩 +天 +连 +锁 +宏 +汇 +厦 +印 +象 +S +馆 +饮 +何 +叶 +馍 +锦 +标 +志 +上 +海 +黄 +浦 +化 +政 +执 +法 +广 +东 +老 +年 +共 +务 +研 +究 +武 +汉 +档 +案 +L +本 +油 +不 +使 +银 +卡 +德 +壹 +作 +多 +润 +滑 +U +V +W +尚 +约 +超 +越 +展 +港 +体 +彩 +液 +气 +折 +哈 +五 +暖 +哥 +烫 +甬 +涛 +建 +筑 +刚 +网 +纱 +窗 +帘 +风 +眠 +艺 +术 +由 +吧 +肤 +• +形 +设 +计 +羊 +火 +锅 +洛 +塔 +做 +喜 +雪 +诚 +正 +办 +夏 +傅 +西 +服 +双 +梅 +婚 +摄 +项 +租 +房 +沟 +炎 +灰 +指 +址 +二 +层 +速 +宾 +早 +唐 +精 +修 +洗 +衣 +冰 +柜 +琶 +洲 +派 +出 +R +d +u +澳 +投 +资 +号 +居 +介 +昊 +好 +下 +停 +高 +回 +铝 +G +Y +Z +窖 +轩 +苏 +· +御 +钵 +晾 +遇 +见 +祥 +如 +意 +洪 +府 +导 +才 +厂 +直 +沙 +泥 +配 +件 +党 +平 +李 +向 +轮 +周 +口 +颜 +就 +景 +韩 +霞 +医 +礼 +州 +白 +云 +古 +奥 +格 +汽 +新 +北 +烤 +y +长 +辉 +旅 +游 +左 +转 +米 +廣 +告 +焖 +鸡 +镇 +各 +F +s +i +牌 +策 +划 +推 +拉 +开 +锈 +钢 +防 +胎 +祭 +女 +招 +珍 +津 +粮 +维 +通 +子 +权 +交 +咨 +询 +位 +已 +谢 +晚 +末 +百 +友 +低 +至 +傲 +帝 +纪 +图 +徽 +纳 +住 +材 +庄 +b +p +伊 +甸 +劳 +遣 +艾 +灸 +幸 +狐 +狸 +桂 +林 +科 +野 +批 +零 +囍 +鸭 +飞 +雲 +書 +畫 +恭 +头 +袖 +布 +庭 +智 +慧 +D +选 +铺 +烈 +王 +芳 +药 +习 +青 +打 +蜡 +呢 +商 +为 +快 +丁 +舞 +跆 +淀 +委 +备 +煲 +质 +量 +盖 +鲜 +盒 +部 +疆 +辰 +络 +会 +淋 +淮 +膳 +芝 +士 +绒 +衫 +杏 +槐 +院 +胖 +烧 +饼 +条 +寓 +侬 +瞰 +敏 +久 +把 +散 ++ +观 +翠 +阁 +型 +请 +陶 +专 +磊 +喇 +叭 +马 +瓦 +罐 +煨 +寳 +貿 +豪 +吊 +顶 +義 +藝 +術 +顺 +睫 +半 +永 +姐 +擀 +罡 +杨 +待 +阿 +腔 +颌 +晨 +副 +鱼 +移 +川 +床 +铣 +块 +乳 +K +呈 +禾 +扭 +伤 +关 +膜 +骨 +坏 +死 +力 +“ +评 +” +余 +记 +猪 +孕 +婴 +陈 +唯 +旧 +书 +M +羽 +调 +解 +员 +汾 +竹 +味 +雕 +垃 +圾 +走 +进 +益 +寿 +千 +里 +蒲 +庙 +榨 +落 +附 +众 +宫 +廷 +桃 +酥 +昌 +欣 +抗 +裂 +渗 +四 +季 +麦 +硕 +脑 +潮 +汕 +杂 +咸 +容 +纤 +俱 +拆 +迁 +处 +货 +阳 +自 +田 +J +静 +瑞 +日 +贷 +款 +估 +过 +户 +后 +刻 +名 +聘 +师 +费 +课 +夹 +® +况 +源 +税 +征 +收 +馈 +乡 +湖 +井 +靖 +江 +数 +卖 +刀 +郎 +三 +两 +七 +酉 +库 +土 +求 +到 +期 +湘 +妈 +妆 +喷 +画 +卤 +菜 +姚 +表 +驾 +校 +杭 +颐 +秋 +职 +苍 +梧 +球 +遍 +看 +淘 +默 +片 +写 +真 +绘 +亚 +克 +字 +善 +溢 +歡 +衡 +: +胡 +春 +榮 +济 +秸 +坎 +器 +械 +敬 +亭 +律 +皮 +担 +筋 +凉 +灌 +肠 +锐 +隐 +眼 +镜 +造 +免 +放 +盘 +邢 +台 +先 +的 +个 +性 +辅 +构 +消 +残 +r +恩 +饺 +宸 +宇 +露 +样 +炉 +深 +巷 +● +插 +者 +珠 +退 +菱 +鼻 +秘 +传 +统 +酵 +绿 +含 +添 +剂 +蚕 +丝 +套 +松 +虹 +踏 +农 +k +变 +劉 +响 +娟 +呵 +托 +雅 +迪 +合 +受 +十 +远 +立 +盗 +鹦 +鹉 +首 +排 +序 +境 +c +购 +守 +腰 +妹 +流 +鲢 +吃 +g +减 +兰 +额 +存 +预 +置 +悦 +签 +涮 +脆 +栋 +县 +— +影 +视 +听 +诊 +乾 +坤 +盛 +然 +宴 +石 +橱 +梯 +搓 +拖 +鹰 +实 +兄 +弟 +渔 +带 +徐 +頡 +范 +睿 +缆 +押 +简 +胜 +贝 +佛 +玩 +Ω +饯 +炒 +糖 +警 +月 +培 +基 +八 +义 +控 +稀 +闵 +陇 +第 +荣 +棋 +邹 +泉 +池 +甘 +贵 +钦 +巨 +总 +碗 +拿 +雄 +伟 +属 +结 +亮 +姿 +梵 +运 +息 +玺 +竞 +鲲 +鹏 +与 +冈 +瓷 +塑 +照 +重 +庆 +弗 +尼 +留 +铪 +弥 +饵 +镦 +巧 +兹 +宗 +馄 +饨 +码 +融 +釜 +佰 +業 +扑 +换 +屏 +蛋 +糕 +Λ +蔬 +瓜 +墙 +藏 +夜 +盟 +; +翻 +腐 +贴 +砖 +毛 +峰 +г +寄 +私 +边 +煌 +馨 +岭 +朝 +菲 +目 +避 +風 +塘 +式 +劵 +钟 +威 +胶 +z +底 +' +/ +次 +芙 +灵 +刺 +柿 +媒 +妇 +汗 +激 +示 +霍 +强 +题 +复 +哦 +, +霸 +j +欧 +俪 +鸿 +運 +围 +削 +榻 +蛟 +帐 +篷 +振 +反 +郑 +仕 +恒 +闸 +肯 +玻 +璃 +俗 +互 +相 +攀 +比 +滤 +军 +队 +离 +确 +凤 +纯 +枕 +只 +蓝 +筒 +整 +种 +螺 +母 +训 +凯 +省 +伪 +协 +清 +蛙 +频 +央 +奶 +冷 +择 +我 +们 +没 +错 +验 +雷 +杰 +辛 +啤 +谊 +己 +蝎 +组 +腾 +仔 +尾 +巴 +严 +君 +宜 +再 +鲁 +迅 +帽 +颖 +别 +致 +责 +任 +准 +罕 +启 +温 +需 +登 +杜 +良 +其 +湾 +测 +起 +丹 +斓 +感 +未 +鹅 +魅 +族 +妻 +肺 +角 +汪 +豫 +砂 +柳 +磚 +血 +病 +航 +枫 +叉 +浇 +焗 +怡 +稻 +槎 +宽 +串 +综 +治 +报 +勿 +吸 +蒸 +扶 +扁 +沪 +草 +勇 +琪 +丶 +伞 +紫 +虾 +嘿 +冬 +薪 +咖 +啡 +诉 +拌 +炖 +趣 +班 +伸 +缩 +q +酬 +朗 +蔡 +莲 +卷 +圣 +痛 +在 +违 +章 +犬 +姜 +驻 +群 +净 +效 +你 +麒 +麟 +郡 +常 +酷 +享 +补 +》 +今 +蜘 +蛛 +梳 +鼎 +耒 +玥 +莎 +坛 +墅 +暴 +笼 +缔 +敖 +肥 +寰 +浩 +粒 +也 +芦 +敢 +追 +卓 +供 +耳 +焊 +氩 +弧 +赖 +召 +捷 +钣 +虎 +崇 +寺 +H +Z +L +酱 +页 +赁 +稞 +宠 +孚 +寸 +炭 +念 +锋 +雀 +巢 +思 +冻 +羲 +输 +歌 +毂 +改 +曲 +她 +彭 +荒 +坪 +愿 +帆 +洁 +止 +辆 +参 +颈 +鹿 +漆 +森 +骏 +晓 +铭 +这 +是 +裤 +知 +度 +泵 +谷 +旗 +舰 +漕 +够 +更 +衔 +岁 +还 +犹 +? +刘 +遥 +蹈 +長 +规 +菊 +递 +陕 +萍 +齐 +翡 +赌 +要 +找 +版 +盐 +禁 +充 +豊 +着 +最 +奇 +讯 +读 +鸣 +昕 +诺 +莉 +雨 +熟 +w +荟 +瓶 +缝 +纫 +检 +损 +张 +少 +樱 +箭 +钻 +此 +若 +船 +芯 +& +兵 +割 +摸 +叔 +幅 +震 +讠 +根 +饸 +伴 +唱 +戏 +载 +披 +萨 +蟹 +茜 +均 +翼 +账 +慎 +谐 +兼 +帛 +诱 +惑 +媚 +匕 +貢 +棒 +沂 +禅 +蚊 +趟 +等 +弄 +摆 +兽 +宵 +幻 +】 +突 +破 +扣 +畅 +潢 +瘾 +盆 +算 +隆 +虫 +睛 +鹤 +曼 +尖 +埔 +将 +授 +菘 +驰 +牙 +练 +壶 +岗 +午 +应 +磁 +汝 +財 +進 +俊 +鸟 +绣 +颗 +醋 +贤 +叮 +咚 +粤 +蜂 +播 +铮 +燕 +树 +嘴 +惠 +完 +勤 +钥 +匙 +继 +续 +裕 +Q +幢 +x +奋 +柏 +查 +洱 +途 +录 +轿 +榕 +圆 +磐 +认 +刮 +痧 +斤 +压 +潜 +宿 +咕 +噜 +喵 +覆 +浆 +骜 +仰 +历 +盈 +栏 +镶 +馒 +皇 +铃 +仪 +像 +碟 +诗 +倩 +牢 +國 +步 +缴 +以 +言 +黛 +援 +甜 +麗 +柠 +檬 +→ +买 +宋 +每 +六 +挖 +屯 +掘 +圈 +忆 +蒙 +扯 +汁 +触 +及 +巫 +率 +注 +册 +湯 +厉 +! +赛 +遗 +审 +荨 +祖 +恶 +魔 +瑜 +伽 +他 +链 +尊 +磨 +冀 +孩 +聪 +崧 +澜 +弯 +轨 +劲 +廊 +奠 +晶 +槽 +纹 +镀 +锌 +郸 +疹 +荘 +驿 +耀 +郏 +丨 +桑 +剔 +茴 +朋 +返 +炫 +箐 +嵩 +探 +独 +抛 +猫 +裁 +澄 +嵌 +齿 +蘭 +麺 +臻 +晋 +賀 +值 +罗 +捐 +赠 +靜 +學 +妍 +妙 +桶 +車 +卉 +邮 +婷 +倪 +泾 +钱 +擎 +彪 +痕 +咪 +邀 +伦 +非 +拳 +舍 +绍 +挂 +靠 +丫 +娃 +试 +潭 +苹 +闪 +琴 +声 +睡 +醇 +¥ +冒 +戒 +廉 +棚 +娱 +考 +级 +故 +è +蔚 +泡 +顾 +琳 +杠 +舒 +适 +绕 +荷 +悠 +肝 +胆 +胃 +横 +依 +慕 +势 +袭 +媳 +界 +弘 +眉 +泸 +贰 +傻 +旭 +茂 +茅 +染 +固 +靓 +增 +扫 +燃 +灶 +毒 +烙 +髪 +俏 +紅 +開 +炸 +寻 +% +椹 +酿 +核 +蓉 +绅 +因 +急 +啊 +祯 +宣 +施 +紧 +抵 +邯 +翔 +另 +滋 +瀚 +借 +氢 +沫 +槟 +榔 +览 +玲 +厘 +丸 +亨 +沥 +混 +凝 +肩 +胸 +那 +莊 +梨 +幕 +葛 +黑 +莱 +凡 +剑 +荆 +旋 +从 +臨 +門 +肌 +献 +赏 +许 +丢 +失 +概 +负 +漫 +鮮 +铸 +苗 +乘 +玫 +铂 +嗨 +席 +毅 +岛 +匠 +邦 +農 +肴 +湃 +瑰 +怀 +3 +菠 +萝 +蒂 +泛 +昆 +邻 +右 +勁 +畸 +刑 +辩 +而 +议 +喝 +榞 +莞 +断 +霖 +辽 +乌 +怕 +滩 +奕 +橡 +隔 +圳 +咬 +芬 +馅 +涡 +封 +釉 +飘 +マ +シ +サ +ジ +泊 +扎 +甩 +斬 +访 +稳 +恋 +當 +佩 +黎 +奈 +烘 +棕 +券 +椒 +醛 +引 +裱 +旦 +盱 +眙 +旁 +穗 +赔 +尧 +赵 +难 +绳 +陪 +锭 +卢 +冲 +绝 +揽 +〇 +脸 +拔 +孙 +爆 +饹 +寶 +楚 +岳 +氪 +篇 +捞 +斋 +栓 +端 +扒 +钜 +侨 +桌 +几 +詩 +帕 +絲 +爽 +茗 +编 +發 +救 +孤 +困 +玉 +杯 +涌 +提 +袋 +汛 +署 +褔 +匾 +奖 +煮 +晟 +觅 +罚 +狗 +龍 +氧 +資 +忠 +乖 +馋 +让 +瑩 +繡 +障 +泳 +椎 +蓄 +泽 +兑 +蝶 +击 +描 +吴 +茸 +窝 +柔 +種 +仁 +圃 +笔 +仙 +顿 +舟 +宰 +给 +杆 +亲 +遮 +毯 +陽 +丘 +除 +害 +骑 +韶 +坚 +功 +显 +说 +演 +坐 +産 +冯 +弹 +韦 +橘 +晒 +澡 +斗 +尝 +取 +橙 +摇 +蕊 +殊 +魏 +樊 +模 +束 +卜 +宛 +素 +墓 +积 +透 +鲈 +孟 +枪 +荔 +舌 +坦 +状 +篓 +袜 +虑 +患 +纠 +纷 +崽 +笋 +蓬 +跌 +渐 +翟 +籽 +碍 +疼 +腿 +脊 +轴 +嬰 +翅 +瑾 +丄 +搬 +跃 +伐 +宅 +仟 +岩 +葱 +蘸 +睐 +战 +孝 +( +) +寨 +檀 +楠 +煎 +贫 +饲 +陵 +普 +熙 +宙 +翰 +钅 +袁 +郊 +昶 +捆 +擦 +圪 +硫 +脲 +桐 +矫 +秦 +硅 +藻 +态 +誉 +猛 +腩 +渝 +拾 +挥 +侠 +痔 +瘘 +挡 +堡 +烽 +贾 +華 +采 +予 +辊 +沌 +坝 +堆 +梁 +牡 +熨 +耕 +鹌 +鹑 +豹 +履 +植 +觉 +鲤 +醉 +菇 +筝 +蜻 +蜓 +莫 +闯 +涯 +乃 +剧 +墨 +革 +雾 +掌 +煤 +肾 +扦 +藕 +命 +齋 +漏 +芭 +荧 +創 +偉 +順 +納 +湿 +鸥 +即 +弦 +驶 +疾 +纂 +闺 +察 +枞 +浪 +碳 +盾 +姻 +锥 +滏 +禹 +畵 +闽 +缓 +邝 +桦 +又 +渡 +瘦 +啦 +逍 +爪 +壽 ++ +娌 +繁 +纟 +柴 +翁 +垂 +钓 +促 +沐 +龄 +短 +溶 +淼 +去 +熏 +漾 +咀 +嚼 +壳 +騰 +肚 +了 +敲 +膏 +艇 +卿 +绞 +冚 +肿 +胀 +楷 +瀛 +嫂 +诞 +湛 +灾 +募 +… +漂 +奔 +葡 +萄 +搏 +伍 +曹 +慈 +; +牧 +淞 +熊 +穿 +孔 +沧 +绸 +丧 +葬 +孛 +赢 +聊 +段 +貴 +堵 +滁 +沈 +馥 +冮 +婦 +羅 +废 +荤 +倍 +耐 +姓 +瀘 +痘 +鱿 +仿 +差 +降 +峡 +斜 +慢 +恢 +切 +番 +茄 +薇 +脉 +驭 +尿 +耗 +朱 +疯 +狂 +储 +虔 +砍 +旨 +珊 +萊 +堰 +牵 +阖 +曾 +涎 +蠡 +捕 +莺 +凰 +据 +咏 +悍 += +悟 +夷 +跟 +妊 +枣 +什 +么 +拍 +稽 +炮 +粘 +脱 +樂 +谨 +溪 +董 +氟 +芒 +爵 +吞 +抄 +扬 +识 +Ⓡ +恺 +倾 +妮 +貂 +阪 +赣 +炙 +★ +撕 +焙 +猬 +岸 +腱 +尃 +斑 +頭 +举 +近 +揭 +甫 +必 +橄 +榄 +薯 +叠 +毓 +兆 +⊥ +芊 +朵 +锨 +淳 +糯 +抓 +钧 +闭 +异 +佑 +篮 +丑 +怪 +玖 +腹 +鼠 +赐 +隍 +鳝 +倡 +惊 +阜 +枇 +杷 +㸃 +鸽 +鲫 +沼 +睦 +芜 +绽 +狮 +滬 +瘀 +疚 +秤 +缺 +襄 +鳳 +藥 +凌 +抚 +丞 +栈 +硬 +谭 +亍 +巡 +判 +蒋 +岚 +映 +初 +敌 +曙 +逢 +肘 +筷 +濠 +伯 +葉 +鏡 +菌 +蘇 +尤 +谱 +乔 +貝 +祛 +h +殡 +暨 +殿 +腊 +厕 +迈 +趋 +淇 +桔 +尺 +媄 +奓 +娄 +祺 +希 +望 +叁 +袍 +缸 +挑 +辭 +舊 +歲 +飲 +姣 +艳 +俄 +宦 +塾 +茱 +【 +戴 +玄 +践 +邱 +斌 +候 +弍 +虚 +醒 +镂 +碎 +锤 +# +妥 +《 +鉴 +辑 +骝 +約 +烛 +冶 +乎 +钝 +陂 +愛 +吹 +穆 +辐 +谦 +疮 +粽 +E +V +R +暗 +隹 +亻 +筏 +~ +弱 +索 +娜 +拇 +筛 +杀 +陆 +淡 +兜 +往 +藤 +萃 +榜 +贡 +飾 +經 +綸 +钰 +贞 +颛 +症 +嘻 +褥 +帅 +奉 +盔 +澈 +锯 +灡 +泓 +哪 +彬 +癌 +峩 +芽 +锡 +絮 +鄂 +『 +泗 +砭 +』 +迷 +遁 +羿 +臣 +搭 +饿 +莆 +瀑 +| +笨 +略 +驳 +禧 +簧 +猴 +優 +币 +碱 +熹 +粑 +铰 +辫 +卧 +杉 +危 +豐 +鞭 +記 +兿 +聖 +似 +乙 +胚 +茭 +吻 +碚 +舜 +赫 +否 +鳯 +答 +疑 +磅 +刁 +框 +亏 +柱 +浮 +归 +撑 +迦 +尘 +銀 +渎 +葵 +偿 +潘 +垣 +终 +忘 +颂 +∧ +И +炔 +氮 +祸 +黔 +侧 +疏 +浚 +嚞 +糊 +句 +扌 +勘 +争 +咅 +圗 +尽 +涂 +胗 +幺 +疤 +嘀 +嗒 +滚 +痣 +逗 +節 +髙 +随 +懋 +畜 +敦 +令 +坑 +栽 +蝴 +跳 +伏 +裹 +懿 +璜 +烨 +匹 +蚝 +偏 +禽 +史 +努 +细 +昇 +晴 +‘ +貌 +缤 +珂 +蕾 +閏 +鞍 +肖 +钉 +島 +の +珑 +璇 +庵 +厝 +戈 +粱 +倒 +嶺 +妞 +赤 +父 +姨 +飙 +狼 +轻 +號 +枢 +纽 +幽 +° +掏 +誠 +闻 +猜 +G +I +A +俭 +皆 +匆 +忙 +贯 +彻 +葒 +蕃 +晏 +柘 +纶 +∶ +喱 +缅 +累 +專 +ㆍ +氣 +跑 +曜 +占 +姆 +蔓 +惦 +倫 +愉 +垦 +洽 +娇 +滘 +泷 +郅 +焕 +顔 +槿 +澧 +箔 +浙 +朕 +衰 +俺 +逆 +é +捧 +奎 +焦 +稷 +铅 +矿 +忄 +韓 +燎 +濤 +钊 +蕙 +携 +榆 +沉 +鳶 +潍 +蹄 +皖 +啵 +铄 +夕 +汥 +乓 +炬 +棵 +衤 +菏 +饶 +’ +问 +賓 +喻 +閣 +薬 +攻 +兔 +熬 +钎 +呱 +谌 +吒 +乱 +邪 +煞 +耄 +梓 +摊 +幂 +豌 +「 +」 +樟 +脖 +苦 +荞 +喽 +攸 +熘 +竺 +蔻 +获 +咻 +薰 +駿 +挝 +镯 +坠 +尹 +萧 +陡 +坡 +輕 +" +窃 +戚 +撒 +煜 +蹦 +颁 +皙 +椰 +愚 +很 +憨 +馬 +壕 +译 +昂 +延 +俞 +茵 +棱 +谈 +桢 +蛳 +炝 +钭 +唇 +點 +審 +喊 +樓 +榭 +琉 +呷 +哺 +③ +巩 +乒 +婕 +蒜 +厚 +媛 +滙 +哲 +沿 +▏ +渭 +硼 +阴 +持 +東 +决 +筹 +并 +隽 +忧 +邑 +骄 +诵 +夬 +沁 +蜀 +卦 +礻 +懒 +浅 +阅 +卯 +炕 +藜 +汐 +莜 +碣 +雞 +艮 +洞 +← +逹 +郝 +乍 +鲨 +湟 +迮 +竿 +葫 +誌 +劝 +浑 +儒 +彦 +燚 +喏 +酪 +極 +抢 +般 +禮 +墩 +珀 +簡 +廖 +稚 +芃 +纵 +灿 +網 +電 +枝 +粟 +吗 +妃 +麵 +催 +著 +仃 +揚 +汀 +绵 +剛 +堅 +▪ +赞 +佬 +该 +萱 +阻 +颊 +羔 +淑 +呼 +铕 +坞 +綢 +盼 +漢 +勐 +晰 +孬 +楊 +徒 +崔 +` +豚 +脯 +酝 +溜 +厢 +沽 +龟 +励 +鳄 +涉 +邺 +笙 +谋 +唢 +呐 +伙 +磷 +溝 +栖 +秃 +肛 +裟 +菩 +绎 +阎 +庚 +彝 +佐 +拨 +勒 +個 +靴 +蜕 +喆 +吕 +狱 +辜 +且 +嫁 +裳 +逊 +丛 +棍 +抽 +叫 +烹 +饪 +键 +粗 +吾 +滇 +喉 +ä +嘎 +芸 +仲 +瓮 +允 +跨 +犀 +煦 +凿 +寬 +刃 +肢 +陳 +猎 +來 +骓 +债 +師 +範 +涤 +锣 +侯 +皂 +棠 +萌 +哒 +摘 +匝 +浓 +骞 +樸 +碑 +耘 +勋 +疣 +叻 +潼 +弓 +须 +趙 +欠 +| +瞳 +堤 +瘤 +輪 +際 +團 +刹 +射 +祎 +驴 +佧 +崎 +礦 +遂 +骆 +驼 +污 +仆 +[ +] +@ +莓 +潞 +腕 +泪 +拐 +菁 +呆 +陟 +诠 +佗 +函 +箕 +浒 +翘 +亘 +酌 +郫 +麓 +鄉 +場 +緣 +璐 +浜 +內 +奂 +揸 +愧 +诸 +届 +凳 +扇 +灏 +佤 +達 +臭 +慶 +嫚 +蚁 +谛 +ɔ +妯 +薛 +娘 +捏 +旱 +蟠 +昔 +課 +挺 +扳 +桩 +籁 +駕 +匯 +亞 +笠 +荠 +郦 +隧 +吓 +禄 +称 +箫 +鋪 +孫 +彼 +韭 +赋 +丙 +昭 +舶 +璟 +憾 +掉 +渣 +煊 +奴 +则 +卅 +秒 +挞 +铖 +颍 +栅 +括 +撸 +鲸 +¥ +驹 +镁 +钛 +覃 +邓 +帜 +鄺 +寝 +涨 +鲍 +郁 +薄 +寇 +咳 +> +琥 +靛 +規 +劃 +會 +顽 +癣 +飯 +垛 +或 +悔 +楽 +徳 +爬 +浏 +燈 +晗 +媽 +馿 +晕 +繪 +圖 +標 +焱 +躁 +麋 +论 +刊 +灞 +傣 +榴 +龚 +罩 +醫 +É +疫 +绥 +拦 +卸 +鎮 +垒 +硚 +連 +较 +窕 +蕉 +勝 +蔷 +裝 +虞 +胳 +膊 +痒 +涵 +粪 +裘 +\ +瀾 +醚 +覺 +烂 +贩 +Ⅱ +亩 +抿 +逐 +參 +З +毡 +肽 +敷 +吖 +滴 +例 +鈴 +抖 +閑 +隋 +骗 +鲮 +玑 +撼 +郴 +[ +撤 +從 +園 +搂 +壤 +遒 +坋 +纬 +讼 +皓 +渊 +虽 +踪 +盤 +嘣 +峨 +嵋 +瑶 +荐 +殖 +鞘 +覌 +蓓 +拢 +涩 +呦 +腌 +苪 +墟 +埠 +喬 +姬 +畐 +砀 +𣇉 +昀 +铵 +夺 +衬 +棺 +窦 +腻 +洒 +枉 +間 +嬉 +舫 +檔 +耍 +鯨 +粼 +珞 +娣 +俩 +圭 +杼 +鸳 +鸯 +現 +鳞 +拥 +絡 +復 +恂 +顏 +軒 +茨 +厄 +雍 +倚 +雁 +苔 +藓 +& +柚 +亢 +逃 +眸 +馐 +矾 +鹭 +爸 +缎 +耶 +偷 +镗 +氛 +醪 +糟 +溉 +剐 +錦 +偶 +憩 +镐 +錧 +庞 +賢 +戶 +鹃 +兮 +钩 +邨 +覚 +屈 +娅 +俵 +敟 +瘊 +阶 +遵 +曦 +妤 +茉 +滞 +珏 +啰 +径 +勃 +篱 +扩 +姑 +厮 +職 +㐂 +垚 +癫 +痫 +茯 +苓 +K +N +膝 +鷹 +熔 +窑 +镖 +螃 +泌 +础 +錢 +锂 +侣 +桉 +霜 +魂 +凉 +役 +塗 +凬 +糙 +粹 +纲 +滕 +濮 +闿 +毕 +昵 +鄭 +哚 +椿 +馫 +蚨 +莹 +泼 +ü +仞 +肇 +砼 +枱 +屌 +跖 +佘 +抱 +見 +芷 +砚 +岢 +晖 +糁 +濟 +翌 +瘢 +疙 +瘩 +噢 +拜 +箩 +蚂 +菀 +芹 +劈 +矸 +痨 +嫩 +鼓 +鲱 +怎 +虏 +靡 +皱 +释 +鴻 +滿 +糍 +㐱 +烊 +霆 +骐 +桼 +沾 +苟 +徕 +碾 +邵 +崛 +潤 +揪 +佶 +雎 +臊 +瞬 +岐 +棟 +锻 +❋ +惩 +淄 +# +蛤 +瑙 +逅 +凹 +凸 +茬 +咽 +彤 +劇 +瓣 +侈 +惜 +咔 +讨 +孖 +氨 +酯 +賴 +漳 +嘟 +竖 +礴 +芮 +雯 +词 +塞 +柒 +趾 +趴 +锘 +銘 +朴 +歸 +弋 +〉 +琼 +蕴 +符 +谣 +肃 +谥 +荥 +氵 +脂 +崃 +㙱 +挣 +瑭 +绶 +漯 +鬼 +骋 +姗 +崖 +壬 +祠 +織 +唔 +堑 +肪 +‧ +炊 +笃 +產 +苝 +埌 +竭 +析 +琅 +穴 +棘 +铎 +戀 +亦 +栾 +睢 +邸 +珈 +朽 +刨 +褂 +啃 +操 +丈 +機 +構 +魚 +汶 +閃 +膽 +陋 +哮 +喘 +帼 +澤 +綫 +氰 +胺 +些 +呀 +紗 +飬 +勺 +荻 +叙 +嘢 +霉 +│ +胞 +熠 +踩 +臂 +犯 +罪 +婁 +態 +陌 +窄 +伈 +壮 +杖 +跪 +帥 +衢 +燦 +燘 +仅 +扮 +闷 +悸 +铱 +循 +剃 +哎 +茹 +闫 +① +蘑 +钙 +⑪ +爍 +_ +應 +粵 +挽 +䝉 +尓 +枸 +杞 +握 +濑 +鏢 +卑 +蛇 +沔 +撬 +碶 +簸 +耦 +颠 +② +醴 +遠 +谅 +F +T +窨 +哨 +拱 +笛 +硒 +糜 +㎡ +瞿 +喀 +寕 +夀 +唛 +哆 +雙 +訓 +孵 +挎 +闰 +谚 +嗽 +戋 +烜 +茫 +護 +膚 +迹 +莘 +既 +獭 +鎖 +2 +輝 +講 +複 +荫 +a +r +黃 +琦 +廰 +懮 +務 +幛 +哇 +杳 +辖 +褪 +栎 +/ +挫 +述 +炼 +懂 +误 +* +歇 +籍 +抑 +舱 +捡 +矩 +毫 +诈 +株 +嘛 +抹 +渠 +它 +- +拟 +挤 +穷 +廿 +羞 +谁 +截 +钳 +搞 +填 +但 +焰 +炳 +匀 +蜗 +饱 +酶 +奏 +± +吨 +× +某 +悬 +暇 +礁 +辈 +毁 +契 +亡 +悉 +稍 +绑 +骤 +尴 +尬 +澎 +韧 +烷 +~ +堪 +詹 +搜 +妾 +祁 +1 +惧 +酮 +蚌 +恨 +谜 +绩 +叹 +侦 +$ +朔 +阵 +惯 +烁 +绪 +堇 +燥 +灭 +忽 +彰 +哟 +歧 +败 +烦 +恼 +逾 +. +肆 +虐 +枚 +距 +喔 +翎 +伶 +措 +却 +帖 +竟 +拒 +浸 +褐 +圩 +勾 +埋 +驱 +吐 +阡 +柑 +骚 +氯 +磺 +仍 +啥 +匪 +臀 +蛮 +咋 +剥 +孜 +硝 +钮 +潇 +砸 +無 +遭 +暂 +痴 +梗 +挪 +赴 +胁 +惨 +衍 +霾 +℃ +扰 +溴 +酰 +轧 +弃 +瑕 +苞 +踢 +迫 +妖 +畏 +² +恤 +缕 +厌 +逻 +枯 +稣 +? +迩 +挚 +擅 +删 +摔 +岔 +唤 +庐 +宪 +隙 +忍 +勉 +陀 +摧 +矮 +耽 +剩 +榛 +蚀 +峻 +※ +烯 +囊 +侵 +愈 +雇 +亳 +泄 +欲 +浣 +讽 +噶 +瑚 +瑟 +羚 +赶 +拯 +阔 +淆 +雌 +坂 +恰 +哭 +慌 +碌 +酚 +祈 +琢 +慰 +骂 +羯 +悲 +裸 +筱 +替 +欺 +碰 +桓 +躺 +稿 +螨 +矛 +孢 +恐 +怖 +镊 +敛 +惟 +甚 +C +拽 +俯 +叛 +诬 +陷 +鸦 +< +爷 +黏 +噪 +仑 +璨 +仗 +辟 +闹 +褚 +咯 +贼 +捉 +唑 +锰 +钠 +秉 +苣 +秩 +聿 +罢 +僧 +嫌 +☆ +钒 +乏 +阮 +痿 +拘 +肋 +漠 +婿 +癸 +髓 +璧 +渍 +喂 +镍 +隶 +疲 +炜 +旬 +哑 +耿 +斥 +膀 +轰 +惭 +恳 +瘪 +哝 +嗓 +泣 +忸 +怩 +劫 +捂 +嚎 +悄 +蹲 +黯 +咧 +贻 +搅 +瞧 +柬 +蠢 +垮 +怒 +睬 +扛 +颤 +眯 +蟆 +吼 +窘 +吆 +滔 +凶 +狠 +愤 +佣 +聂 +跻 +迟 +脾 +凑 +绉 +抬 +吵 +瞌 +耸 +牺 +牲 +瞪 +膨 +惹 +揉 +懦 +犟 +憋 +绰 +惋 +咙 +蔼 +躲 +狡 +黠 +淌 +辕 +辙 +搁 +呃 +吩 +咐 +嚷 +庸 +咱 +噩 +斩 +哧 +歹 +昏 +绊 +歪 +妨 +吟 +啼 +慷 +慨 +忿 +眨 +漓 +轶 +扔 +贪 +譬 +谎 +捶 +哼 +窍 +啪 +绢 +冤 +屁 +屉 +惕 +擂 +坟 +屡 +辨 +蔑 +脏 +嗯 +擒 +谍 +馁 +愁 +忌 +狭 +怔 +晃 +蜷 +辞 +庇 +擞 +兢 +屑 +拎 +蠕 +睁 +沸 +衷 +矢 +吁 +豁 +曝 +怅 +踮 +坯 +敞 +婉 +狈 +憎 +哐 +跺 +踹 +婶 +羡 +耻 +挨 +搔 +佼 +唠 +鄙 +哀 +梆 +犒 +舅 +妄 +佯 +嘘 +柄 +舆 +荡 +惴 +夸 +瞒 +霹 +雳 +嗬 +瞻 +挠 +缠 +馊 +踱 +愣 +堕 +讳 +漉 +潦 +拭 +歉 +趁 +翩 +僵 +摞 +侄 +怵 +魁 +簿 +怨 +叽 +怜 +瞥 +嘲 +揍 +抡 +唬 +赦 +咄 +逼 +侮 +蹑 +霎 +眶 +诀 +篆 +傍 +瘫 +魄 +捅 +叨 +噼 +祟 +哄 +捣 +仇 +嗷 +娑 +啸 +弛 +捺 +恪 +殷 +缭 +锲 +爹 +拄 +炯 +辱 +讶 +撇 +诡 +睽 +掀 +沮 +岂 +昨 +宕 +趔 +颓 +斟 +蜇 +掖 +诧 +箍 +羹 +诌 +唉 +嚓 +懈 +岑 +趄 +奚 +沓 +懑 +沛 +○ +贬 +忐 +忑 +聋 +蚤 +誓 +怂 +恿 +砰 +拙 +冥 +谓 +襟 +掺 +楞 +咒 +鞠 +诩 +裆 +蹚 +髦 +劣 +匿 +抒 +垢 +嗦 +扉 +苛 +贿 +赂 +搡 +蹭 +鲛 +攥 +舵 +塌 +胫 +琐 +癞 +晦 +崩 +夭 +搽 +咛 +嗖 +褒 +悚 +诲 +怦 +懊 +踊 +揶 +揄 +躬 +懵 +渴 +悯 +喳 +垠 +撞 +吱 +叼 +熄 +吝 +骷 +髅 +趿 +俘 +僻 +猾 +赚 +曰 +抠 +阐 +倦 +楔 +迂 +逛 +铆 +凛 +奸 +逝 +寞 +嘤 +昧 +哗 +癖 +坷 +寂 +姊 +汲 +惮 +呗 +皈 +霄 += +鲶 +褀 +芋 +張 +臺 +< +> +鳌 +汴 +j +昼 +剁 +侃 +體 +硂 +啄 +_ +薏 +砌 +\ +羌 +鹞 +碁 +樽 +畔 +疱 +" +辋 +毽 +↑ +尕 +稠 +獨 +玮 +桁 +莅 +卵 +捌 +鱬 +忻 +醍 +铧 +№ +扞 +涧 +牟 +锚 +浔 +傢 +俬 +] +垧 +涇 +糠 +麸 +掂 +蔗 +笺 +隅 +瘁 +巍 +氙 +葆 +霏 +@ +叢 +秆 +鶏 +缪 +峪 +斐 +缙 +甄 +钯 +` +胭 +眩 +統 +鄱 +盅 +嵊 +铲 +菓 +❤ +呕 +泻 +龅 +圧 +洺 +呛 +π +翊 +餘 +翥 +芎 +铬 +沱 +婵 +裔 +橦 +暢 +煸 +唻 +腋 +莽 +镭 +穂 +樵 +蕲 +乞 +暄 +剖 +狄 +蓟 +捍 +鼾 +珙 +拷 +屠 +茁 +堃 +裴 +皋 +炽 +屹 +頔 +剎 +迺 +廬 +兒 +膠 +脐 +颢 +畈 +竣 +卒 +缦 +蟾 +艰 +夢 +崋 +萘 +撮 +倌 +晞 +荪 +痹 +炤 +娓 +傳 +琨 +筠 +蕳 +髮 +樹 +溃 +疡 +瑪 +峯 +恕 +勑 +洼 +④ +蘘 +鰻 +裡 +夙 +昱 +谕 +钞 +赊 +琵 +坨 +哓 +寅 +邂 +锟 +鷄 +環 +縣 +痰 +矶 +飛 +昽 +痤 +皲 +霓 +馕 +娲 +冉 +赉 +匍 +瓢 +廠 +岙 +親 +稼 +勅 +锄 +^ +為 +戎 +麯 +绮 +* +铠 +設 +浠 +榈 +瞄 +芥 +钿 +泺 +氽 +鴿 +涞 +諾 +麾 +蔺 +祙 +仨 +芪 +囧 +蝇 +褊 +溧 +姥 +嚏 +嗅 +嗡 +崂 +癜 +喨 +扙 +‰ +颅 +恍 +惚 +侍 +↓ +汊 +岽 +涕 +峙 +甏 +溸 +枭 +億 +掩 +蒄 +涫 +拴 +扪 +爺 +補 +歆 +嶪 +遐 +囱 +灼 +札 +邳 +袄 +〈 +岱 +籣 +鐵 +锴 +豉 +鍋 +鋒 +赎 +砋 +垓 +頤 +蓮 +崴 +} +炀 +{ +様 +趵 +飚 +耙 +粢 +泩 +皿 +於 +哔 +匡 +枋 +柛 +溯 +砥 +砺 +係 +犇 +灣 +靳 +禺 +饦 +區 +铛 +鄯 +滟 +鲩 +鈺 +黍 +跷 +楂 +潔 +埗 +靈 +徜 +徉 +嘬 +戊 +铞 +鳅 +秭 +í +猗 +聲 +旌 +酩 +馏 +憬 +實 +鹊 +總 +衖 +矗 +蝉 +囡 +疥 +缨 +ʌ +聞 +钾 +廟 +沅 +娠 +骁 +鍊 +葳 +耵 +沣 +鄢 +笈 +圜 +胪 +啾 +瑁 +蒡 +廓 +夯 +臼 +湓 +煋 +丼 +珺 +瘙 +仺 +矽 +動 +Ƨ +汆 +宓 +弈 +翱 +³ +処 +専 +賣 +跤 +镒 +娽 +蔽 +雏 +琛 +巅 +虱 +龢 +滢 +踺 +壓 +阙 +и +绨 +铍 +斛 +龛 +缐 +飨 +忱 +韬 +嵘 +類 +聯 +嗝 +′ +町 +梏 +蛊 +瑛 +伢 +囗 +淅 +協 +爾 +讴 +菡 +桖 +嗲 +囿 +湄 +诛 +憶 +荃 +棛 +鵬 +屿 +夌 +俨 +弊 +亟 +娶 +缥 +缈 +― +舐 +忏 +瞭 +觑 +岌 +尸 +乩 +砝 +傀 +儡 +汰 +妓 +淫 +轼 +阗 +曳 +岿 +莒 +僚 +掷 +绠 +浊 +眢 +矣 +殃 +哉 +晤 +婢 +鼋 +鳏 +曩 +湫 +偃 +袱 +嶷 +惫 +帚 +悼 +倘 +腑 +撺 +﹒ +涸 +祀 +遏 +猿 +辄 +俟 +绛 +绡 +叩 +呻 +迄 +寐 +逵 +涅 +蒿 +滥 +艘 +镣 +铐 +焉 +惆 +窥 +} +妗 +诘 +簪 +氆 +氇 +兀 +匈 +唾 +渺 +冕 +舷 +僮 +笥 +怼 +伺 +溥 +杵 +捽 +叱 +贱 +袤 +■ +寡 +慑 +馔 +匮 +寥 +捭 +颇 +噤 +媪 +垄 +檄 +顷 +暮 +藉 +莠 +髻 +疵 +窜 +啖 +漱 +溟 +孰 +惬 +旎 +骘 +恙 +瘥 +氓 +黝 +豕 +痢 +鸢 +嫔 +韪 +讷 +磕 +狲 +睹 +︰ +辗 +跬 +瘸 +欷 +抨 +掠 +撩 +睒 +蟒 +涣 +骇 +嫉 +妒 +啬 +驯 +颔 +◆ +舁 +娥 +椭 +诣 +膦 +帷 +摹 +嫦 +狎 +龋 +訾 +涝 +槛 +蛹 +滦 +盏 +胧 +妪 +龁 +凄 +盎 +劾 +觇 +{ +渲 +髯 +衾 +孑 +婺 +萦 +谒 +惰 +桎 +婊 +鳃 +褫 +怙 +à +迥 +鼍 +赀 +─ +甾 +裨 +遽 +瘟 +娡 +陛 +囚 +哩 +浐 +扈 +慵 +桅 +兖 +酊 +舄 +蹴 +佟 +缢 +啜 +吏 +哌 +赡 +掣 +萎 +悴 +屦 +扃 +缚 +棹 +奘 +闱 +唆 +逶 +迤 +绷 +苡 +纨 +郜 +辇 +蒗 +阑 +簇 +怠 +雉 +嘱 +悖 +娩 +殆 +腥 +咫 +阱 +驮 +焚 +瞅 +佻 +聆 +藩 +嗪 +捋 +袴 +泯 +揣 +拂 +袈 +衅 +瞑 +愕 +彀 +蹊 +榇 +滓 +敝 +颦 +咎 +斧 +笞 +脓 +驺 +麂 +腮 +濒 +迭 +翦 +辔 +汹 +隘 +伉 +臧 +癀 +觊 +觎 +琏 +霁 +丕 +龈 +赍 +谴 +谏 +苎 +睾 +祚 +庥 +瘠 +耎 +缜 +秽 +沦 +咤 +⑾ +钏 +抟 +砧 +戍 +衙 +攫 +藿 +愦 +盂 +鸩 +眷 +喧 +瘗 +瞽 +幔 +恃 +苯 +袒 +劬 +踞 +匣 +俚 +眈 +碉 +啻 +〔 +〕 +撰 +戌 +豳 +銮 +亵 +吮 +谬 +镑 +綦 +箸 +褶 +痪 +缉 +嗤 +濡 +膛 +睚 +腆 +糗 +髭 +尉 +锹 +骸 +赟 +殉 +攒 +饷 +茎 +铿 +歼 +挟 +鲠 +峭 +靶 +笄 +碘 +瞩 +涔 +鳖 +抉 +貉 +睇 +嫖 +娼 +衲 +⑦ +讹 +禀 +倭 +徙 +叟 +趺 +毙 +伫 +鸾 +朦 +濯 +怏 +蹙 +玳 +偕 +粳 +驸 +旷 +卞 +爇 +猝 +溺 +喙 +瞠 +□ +昙 +檐 +窠 +蟋 +禳 +逡 +攘 +诫 +穹 +磋 +奄 +踝 +骅 +噬 +彊 +榷 +⑵ +夤 +筐 +璀 +忤 +赧 +篝 +豺 +徘 +徊 +晌 +孺 +丐 +戟 +飕 +蒽 +褓 +遶 +嗥 +纭 +溲 +褴 +庶 +辍 +篡 +剿 +畀 +逮 +酆 +猖 +闾 +犁 +纣 +镌 +怯 +墉 +酣 +溅 +胱 +酋 +铀 +觥 +舛 +唏 +鏖 +肮 +婪 +遹 +呶 +嫡 +倔 +幌 +殂 +戮 +侑 +憧 +赘 +赃 +筵 +呜 +饥 +锷 +鬓 +诮 +诋 +瞎 +祜 +毋 +廛 +迕 +恝 +峥 +颚 +缗 +遴 +蓖 +唁 +恬 +桀 +骠 +獐 +踵 +霭 +剽 +洟 +姝 +雹 +锢 +霣 +溷 +髫 +寤 +惶 +歔 +吭 +俸 +哂 +濂 +厥 +皎 +骡 +喹 +篙 +扼 +咆 +敕 +伎 +嶂 +盯 +狩 +殴 +镪 +蛆 +镳 +骛 +坌 +邴 +谙 +飒 +琮 +Р +П +О +旖 +俑 +饕 +⑤ +糅 +撵 +牯 +蹿 +砣 +婧 +姮 +甥 +紊 +踌 +躇 +谲 +掐 +璋 +谀 +噱 +缄 +嗜 +贮 +嗔 +蚡 +髋 +迸 +侏 +箦 +椽 +蹰 +醮 +萤 +邈 +橐 +栉 +猕 +珰 +恻 +臾 +祷 +兕 +奁 +赈 +蚓 +骼 +澹 +伛 +偻 +俎 +傩 +纾 +鬣 +烬 +钗 +揖 +⑧ +怿 +暧 +鲧 +瞟 +袅 +β +呓 +赇 +蜈 +拮 +谑 +樯 +囤 +氤 +氲 +阕 +宥 +喋 +卮 +娈 +嘶 +圹 +嬖 +诏 +酞 +罄 +恹 +淹 +锏 +蜚 +矜 +蚣 +邃 +鸠 +疸 +掼 +栩 +洮 +耜 +毗 +頫 +畴 +痞 +躯 +悒 +孽 +梃 +绯 +嘈 +诿 +骰 +鬟 +崭 +铙 +斡 +袂 +彷 +渤 +疋 +痉 +挛 +眦 +芈 +啕 +纰 +刍 +忒 +祗 +膺 +畲 +獬 +豸 +Ⅲ +﹐ +庖 +啧 +壑 +襁 +痈 +恸 +诟 +楹 +吠 +痊 +荼 +樾 +苌 +讪 +蹬 +贳 +娴 +潸 +搪 +倨 +纥 +醺 +忡 +拣 +蟭 +鑙 +蜿 +蜒 +酡 +罹 +谩 +◎ +溍 +锗 +麽 +遨 +亥 +泮 +樗 +捎 +伧 +牦 +憔 +幡 +煽 +郪 +眺 +俐 +冗 +漪 +蚩 +痂 +椟 +漩 +嗟 +诽 +谤 +枷 +饽 +棣 +卬 +幞 +帔 +镬 +牍 +诳 +詈 +阆 +掇 +荏 +觌 +逑 +稔 +歙 +缮 +盹 +儋 +厍 +睨 +畦 +酗 +栀 +逞 +徇 +蚯 +摒 +炷 +鹜 +鹂 +谶 +绚 +臬 +罔 +枥 +瓯 +甑 +亓 +庠 +唿 +拗 +谗 +窟 +噎 +岫 +凋 +叵 +牒 +簋 +蛰 +噔 +拚 +鸮 +岖 +蹂 +躏 +徨 +掳 +涪 +屎 +绾 +箧 +拈 +茕 +殒 +黟 +薜 +噉 +嫣 +戛 +涟 +冁 +邋 +遢 +菽 +悭 +囔 +彘 +徼 +⑨ +锺 +顼 +掬 +廪 +捻 +俾 +愆 +窒 +釂 +後 +嚣 +腓 +哽 +铉 +靥 +颧 +疟 +雒 +搀 +汞 +阂 +杲 +唧 +佞 +娆 +妩 +浃 +叡 +⑩ +蹇 +祐 +缀 +谄 +梢 +臆 +胰 +蠹 +胤 +━ +狙 +谳 +俛 +翕 +瓠 +盥 +咂 +衿 +鐘 +惇 +な +て +诅 +畿 +枳 +跛 +泫 +孳 +巉 +飓 +迨 +垩 +焘 +– +恚 +箴 +疽 +讣 +窈 +妳 +噫 +魍 +魉 +爨 +╱ +诙 +狰 +狞 +踣 +汜 +尻 +缁 +⑥ +犷 +闼 +珩 +觞 +鸵 +蝠 +擢 +拧 +蓼 +晁 +瘴 +槊 +邕 +粜 +縯 +豭 +媵 +佚 +衩 +阊 +坳 +湍 +⑴ +铨 +俅 +嚬 +粕 +罘 +畑 +瞀 +瓻 +蹶 +搴 +祧 +冢 +秧 +缰 +邬 +诃 +聩 +糌 +骈 +佈 +┌ +┐ +蜥 +蜴 +痍 +∈ +墀 +渥 +缧 +孥 +咿 +勖 +恫 +刽 +嗣 +郓 +惘 +羁 +蝗 +枵 +绦 +弩 +踰 +馓 +蓦 +黜 +苷 +胯 +遑 +侩 +铤 +惺 +桨 +诨 +砾 +磬 +龊 +骊 +喃 +鬲 +渖 +锉 +坍 +鲇 +苒 +腼 +狻 +猊 +廨 +诒 +蛾 +爰 +裾 +舔 +桧 +裀 +悻 +讫 +奭 +戳 +膘 +倬 +殚 +峤 +颉 +戾 +葺 +薮 +涓 +卺 +饴 +椁 +榧 +镵 +怆 +怛 +翳 +踉 +挈 +迢 +踧 +羸 +胄 +戗 +價 +浼 +喟 +菟 +驷 +俳 +簏 +僦 +桠 +Ⅰ +咦 +^ +掰 +彗 +蝼 +匳 +胥 +⑿ +弑 +冏 +愠 +陨 +罂 +倜 +傥 +搠 +镛 +傈 +僳 +嫜 +鬻 +噻 +鸬 +鹚 +腉 +摁 +欻 +牖 +鹄 +√ +腭 +缵 +肄 +唳 +÷ +钨 +◇ +鸨 +撝 +挹 +黾 +倏 +绐 +麝 +蝙 +睑 +儆 +牝 +猷 +≤ +裰 +啁 +甭 +聒 +蹋 +蓐 +耆 +闳 +骥 +渚 +锽 +逋 +贽 +跋 +獠 +虬 +铢 +嘹 +α +羟 +匐 +肱 +椀 +焯 +鳍 +潺 +殛 +妁 +傕 +蛀 +巿 +偎 +芫 +狝 +楮 +淤 +絷 +珅 +肓 +犊 +镕 +魇 +∩ +氦 +贲 +脔 +窭 +谟 +愫 +媲 +珥 +旃 +磔 +嶙 +峋 +陬 +喑 +琖 +徭 +峦 +摈 +猱 +蕨 +婀 +Ⅳ +舂 +夥 +藐 +驽 +骀 +帏 +谪 +弁 +襆 +镰 +⒀ +窬 +棂 +鞫 +诰 +皴 +玷 +跣 +恣 +绫 +钤 +怍 +篑 +腈 +涿 +姒 +冽 +埒 +巳 +獗 +啮 +阈 +绔 +媾 +簌 +钺 +侥 +砒 +劙 +峇 +阏 +榫 +旒 +偌 +罴 +钼 +坭 +纮 +劓 +刖 +缞 +绖 +苫 +苻 +猢 +脍 +徵 +燠 +冑 +帧 +茧 +罥 +幄 +踔 +愬 +瓒 +辘 +猥 +槃 +荀 +酹 +∵ +锱 +﹑ +囫 +囵 +戢 +愍 +縠 +屣 +忝 +≠ +揆 +崚 +犴 +蹒 +佃 +楫 +獾 +嗾 +窿 +苇 +薨 +绌 +荚 +蕤 +逦 +锵 +耋 +佝 +桡 +晡 +钲 +槌 +檠 +鬃 +讥 +訇 +搢 +泠 +歘 +泅 +暾 +孪 +淬 +妲 +殓 +愎 +祇 +厩 +剜 +蛔 +俦 +迓 +藁 +凇 +跄 +萸 +嗄 +哙 +舀 +珐 +刓 +赝 +噙 +缱 +绻 +遘 +鞚 +媸 +戆 +嵯 +骶 +圯 +仡 +鳜 +赅 +愀 +殇 +膈 +辎 +馀 +滂 +▲ +乂 +襦 +葩 +壅 +砷 +巽 +瀹 +蹀 +躞 +嗫 +嚅 +筮 +瘳 +楗 +诤 +嗳 +皤 +柩 +剌 +忖 +殪 +髑 +钹 +嗌 +蹩 +缒 +囹 +圄 +讦 +钡 +蜍 +臛 +喁 +偈 +氡 +阍 +殁 +淙 +枰 +棰 +轲 +楣 +陲 +蛎 +悌 +岬 +邰 +臃 +搒 +讙 +⒈ +粲 +邛 +粝 +欤 +髀 +豨 +凫 +苋 +榼 +飧 +姹 +阃 +墠 +榱 +畎 +忪 +衽 +腴 +耨 +扢 +氅 +谧 +搐 +罅 +絜 +顒 +诂 +悞 +殄 +≥ +堙 +噭 +橇 +眛 +缳 +釐 +泞 +菅 +汭 +爲 +骧 +湮 +捱 +暹 +噗 +镞 +斫 +仫 +娉 +铳 +碓 +夔 +嫱 +跸 +蛐 +拊 +绀 +疃 +跚 +蓍 +谯 +柢 +钚 +茆 +蜃 +鹳 +刭 +锑 +暲 +篾 +饬 +蒺 +啶 +隗 +燔 +趸 +弼 +燹 +胾 +旻 +浍 +踽 +阉 +衮 +眇 +芍 +绁 +浞 +祓 +嘌 +刈 +葭 +鹫 +揩 +鄄 +⑶ +煅 +炟 +觖 +贇 +魑 +弭 +瓴 +圉 +竽 +莴 +撷 +疝 +镉 +鹘 +觐 +甙 +縢 +嬛 +柈 +僖 +舡 +谮 +孱 +岷 +荜 +坼 +鞑 +⒊ +湎 +赭 +嗑 +碴 +啐 +鲑 +鸱 +芘 +闟 +慙 +焜 +汩 +隳 +芡 +茏 +踟 +赪 +侗 +狒 +窣 +谇 +瞾 +郯 +螫 +纔 +澍 +泱 +瘐 +伻 +蹻 +烝 +燮 +咣 +旄 +鹗 +擘 +酢 +篁 +△ +悫 +淖 +猩 +皑 +戕 +恽 +纻 +髃 +镝 +碛 +侪 +绺 +癔 +谆 +懜 +朐 +阚 +鈇 +刎 +苕 +匏 +蹉 +稗 +郄 +虮 +蛩 +嬗 +儇 +蔫 +豢 +椐 +蚰 +昃 +柞 +峄 +蛲 +曷 +赳 +珮 +杪 +虢 +螂 +呤 +唶 +昴 +鄣 +茔 +仄 +劭 +鞣 +杓 +姁 +薤 +膻 +氐 +醵 +杌 +笫 +穰 +螭 +跂 +褛 +燧 +郢 +哏 +撂 +韂 +﹖ +痼 +琰 +脁 +隼 +穑 +槁 +羖 +僭 +蒯 +孀 +骖 +龌 +潴 +﹔ +盍 +莩 +讵 +跽 +觳 +垝 +橹 +钴 +缶 +鸷 +遛 +翮 +鹣 +汨 +珪 +祉 +鞅 +怫 +缯 +噌 +濞 +庑 +斲 +洙 +趹 +玕 +颀 +轵 +髡 +嘭 +讧 +笤 +⒉ +磛 +繇 +疴 +沬 +趱 +鲔 +铩 +⒆ +跹 +胝 +酤 +寖 +轫 +貔 +嬴 +玦 +滈 +瘵 +曛 +馎 +楸 +晔 +笆 +缟 +庾 +茀 +爻 +弢 +赜 +遫 +睪 +郧 +鲋 +帑 +璆 +驩 +縻 +踯 +鲐 +崆 +峒 +餍 +邠 +螳 +喾 +嗛 +⒂ +颡 +苴 +瞋 +闇 +膑 +帨 +躅 +觚 +刳 +逖 +犍 +掾 +诎 +轸 +揜 +殽 +猃 +狁 +皁 +⒄ +鄜 +郿 +亶 +洹 +荦 +蛭 +紬 +柰 +寘 +羑 +嫪 +侔 +纡 +徂 +鲰 +乜 +餮 +鄠 +氖 +嵬 +虺 +蝮 +锾 +⒅ +埤 +棓 +苄 +悝 +渑 +觜 +莨 +轺 +酎 +鹆 +郾 +秏 +狃 +殳 +瀍 +蟥 +郗 +凃 +淦 +蟀 +昝 +嵇 +檩 +鄞 +荸 +仵 +邗 +铡 +琊 +芗 +蓥 +酃 +嘁 +鲅 +陉 +妫 +蛉 +璩 +濉 +畹 +蚪 +蒉 +溆 +謇 +掸 +仝 +浉 +逯 +麴 +誊 +邙 +仉 +珲 +逄 +邡 +坻 +眭 +磴 +渌 +僪 +埇 +缑 +禚 +沭 +欎 +螟 +笪 +庹 +茌 +邶 +秕 +隰 +秫 +圻 +冼 +杈 +蚜 +祢 +埂 +猇 +浈 +佴 +蝌 +貊 + +© \ No newline at end of file diff --git a/share/qtcreator/examples/15-Utils/fist.bin b/share/qtcreator/examples/15-Utils/fist.bin new file mode 100644 index 00000000000..be382d13408 --- /dev/null +++ b/share/qtcreator/examples/15-Utils/fist.bin @@ -0,0 +1,1313 @@ +~w{quylpuimrfkoaei]af[`dZ^bW[`TY]TX]TX]UZ^X\`Z^c\`e]beaegeijkporwvx}}~tvw\_aMPUMPUKOUGKPBEK=AF8=CBCHGKMMNPPUWWeggorrvxx|||tttlllddd[[[RRRJJJBCC;=>369/28-08-08+/6),3&)1$'/!$,")'%%%$%%$%%& ' (!(")"' "#" %$"'&#('$)($)(%*)(-,,//011466<>>BEEHJJOPPWWW^^^fffnnnyyy}}}tttddeYXYSSSLLLBBB<<<666000+++%%% ''&'''(('''''(!* ",!#-#&/#&/$&0#&/"%.!#-#+"(!%!!!  !! !!!###%&&())++.//212444656999AA@KJJWVV`__hggtrr}|}xuuihhZZZNNNEED===333,,,(((#$$ "#$$%%%%&( *!+!#-!#-!", *)(%#" %%%./.565;<:CA@IHHUVUgfeywwxurhedTQPEB?<:66320..)('"!  $#%'&*,,),/ ")$%'&&&&%%&%%''&%$#!!     ! !# % $#    "! %#"''$/-*623>;;FEDTRRged~}|zwd^[LGD@=951/'#! +  !!"%%$(((-,-1137947;(*2 +!- #."-!,+*)))(())&#! "####$' (#"*##*##*!"( !&$!)'&A?>b``}}xwjc`TLIB;74-*-'%*&%*%$)%#($#&" #     !!$"%!&')+++++******('&%#""!!"##$&&&%%%%$####!%$$222===KKK`_appr}}xvkfd[TTMEE>75-'%  '##,((,))(%%$!!!!$#$&#$&!"$#$!$!$ #! $%%$$$##" ! ! !     +  + + +           !! !!  "!%./2<>ALOQ^_btv{}xymhiXSTIDD>996122,--('&! $!#&#&%#%! # ""#($'+ $( $!$ $$#!           +  +     +        !   + "&+.27:>FINX[`nqvc^_C>?9572.0%!#!""& $ ##! !!"#%%&%##"! !   + !!!! " " " " ! "!          $(('& $ ! +      +!#"##     "! $"' #&"  +!""''+036;ADIUX]qty½pkm\WYJFG511%!"!  !!$ !(!#*&"! $&%"   +   +  + +   +   "% +( +-/0121136"8$:&<&<&<$:#9!76!8#9!863/+'"      +    !!"#"#!( %+$*$! ! #&)/:=DNRWhkoýz{]XY@;<'$& (%(&%(#"&#"&#"&#"&#!'%"(%#)$$)$%+"$,($"""!"''$ !  + !%*- 27"='A",G&1L*5P.9T.9T1X.8Q*5L$.E&>!62/+ *'%"  !"   +#'(%####""&#+#+&#"$)025GHLcdg~niiRLM<78.)*% !! ! $"$%$($"#"       +$ +& ' '#  % +-';#1E&5I+;O4DX=LcFUlP^uXh`rj{ou~wp}hv]kQ`zFUn>Mf6E]+:S#2I(@": 0 " + !# !  !"# +$ +# %)",!&/$)3!'0)!#!( $*$'+)*./16<>AVUWvuwibcSNM=79%!"#$!&%#)$#,(%%%$#  + &* , . -*'(0&<"0G,;T;JcGVnL]uRd|^ogzpztk}`rSeEWr7Hc->Y$3N%?876 3 +/,)&" !  +$* , ,,(! %"+&!'(,@@Ca`blkoYWYJEG<672,-("$!$'""-%&1#%0 #/ .+'# +  ( +1 :'A#0J,;T9HaIYrUd~_oo|tfx\mQbGZw=Ok1B^%6R+E!:. +## ('%%%!  $ *"+ #+"(""0/2IGHgeeonrJIM0/3"$!)#(+&+)%*#%+%&4"%3!10.-+) '$# " #/">%3O7EaGUrXhhxw{fzRf>Sp.B].I 7+ +$ " # #$%$! #((% ! !"+%*2'*2#&.%101RPPpmlecfLKN==B116%%)"#)%+,*0,*2)&/"!)"  + ")%  +   "$& *28'A-8T=IhHXwYim}~|m]pJ^z9Lh+;W!0J(@8 0'  &' $   $)$-"+$,+,866PML}xwghm>?C $!"(,,3,,3 !'#$$$ %!!($#-&&0&&1 "-'  $ ,5)B0;V=HeNZwiwxcvTfEUp0?[!0I#: + " +     +   #' (!("&!% !$ !$""EBAlhh¾jkoKLP359!$)  ) +& )"#,("#(*($ %/$>%0K3?ZBNiU`|jw{xaqO_z@Oh-;R*@3 +*$  +    !#' #*"%)!$("0..GDC_[Z~yywwzPQU027" %&$#%''%!       +   +# +&# %6%1J8D^KWrZfiwyw^lDSl-'   +  !$!% "'(),,+.&%' + + )''TRRy{yUYW9>=(-,#&("% "!'1#(3".% +  !&*+ +' "! +$ +1%A/:UEOl\gvw^l3BY*A 7)   " "   + **.0/2(')213TSUyxzſotpKON,0/""&+!'!'",)$     " %(), 1!?)6TCOm^kxrXjARk'7N!7 (#!   #%)++/)),#"$ 0.0HGIb`cptpZ_[GLJ165##$#*$- )#  $ +$ + " 1#@#0M2@^IWwbox|[k=Md#2H4# + !#  ! !"!# +*,==>YXY^c^8=:$)&!"!&#)!*$& &  "2*E/VO_zoerANk&1M,  $&%$&-#$0"$-%$&'678ZY[MW]#.5  !!$'13#,0"   $'" 35F`hytVb~5?X'?0 ' + -)+8.0;$'/!889hhhzKTZ#,3  "&$$$""&( +# !)$:9E^_o~am=Ic"+C.  % #0-/:%'/  &')CCDonorv|BHN'/    *(4!/ $!.#,8& +  + "/#3 +& + +"2HI[rhs?Jb!)A +   $". )#!#)$$(*),@?Akiiotx=@G$  $$1*90!+!)9.    +(/ 0%;1@YXjnxCMf *A '  ! #$"$")'(/$$*  <9;fddjor>BG%  ","2"3.& +#',+$   2&6OIZsoq}DNg&?( " ".#-)!)&'/$%+" #ECDwst^_c69>& *#1!1-*,. ! + ('&61?Z[jxKWs)3M4 +(  #1 %0'"%%0.0MIKuprfhj005 )$+8%,;"3) +&,4 ,)#/HNZvyfr8B]5 +(&  +  (%)D?Csoqpqr@BD % $0")7$5- ' +'+/ ,$# *)GP\yam)3P , +   +&!&#%IFJ~iiiBCD"$&& "-"/+ % " +% * +* &" )"A6@`ZcS^|-8S6 ! !)#'((2,*4#  )&,XTYffcCCC+./ ! #-#$0-$  +& +) +& +(=8Eedq^k:E]/ ',)%)'(3,,7' 315[W\ghd<<:,--&() #&"#/"#0-& " ! % + -3'F=Hhamdp)2M ( # #$%+"".& !305WRWvvsBC@)))$$%!! !("$/#$2/'  +!0 ;%,JGPpr|S\y!*E +- %  + !$%)(#" &85;fbg|}zGHE)*(#####$!%*,+ # +!!<3:ULTp{}O[v)D (  &+$##$&$*EBGzvzLMK$&$ ##""! +/6 *) +   ##!'!#)69>ikpEEE  ###///(&(!! '!  #3>BTfl~ap1;W % -+  + !()+1# !&CEJ|~QRQ'(' ###" $"  -9=?(&(-,.#"% ('+$  &56BX[i~zKZq"0E '!$%!!%,#',  #&,148fhkklmGFH$#%! !!!#""%!'',! (  #-/F[Q]ser{_q):S* '(   +!(!"#)!!&()-TUYxqwh`gYQXHBI4/7$!( !"$"&$#'!#'!%$$%# #.* #    "$  &"7!,B*5J5>S=EZKRfgkJ\v)B*'%!"" + %*,1 %449styĿ|e]dMEL;3:+#+#" +   + !!$'(''*&%*$%) "'%"!   # /)  "&$ ! '+/BRVg~r=Lf$<'   #   ),-3 &$%+STZuqv\X^HAJ:2<0'1#%  ""! #&"$(!#(!'%# !! !   ! +"  +  " $ $ "   #%# + +'"&9<@S[]qno~fx2A[ 2  # " +  *#$,"$8:?cdigfhKHL617&!)$!$$'$("%"&#'$($ +%",%#.#$- ")&""#$$"  "$&((  + $ (( & #   !'+ ' #' +* ) +& ! + --/C>?UNQgknWg"2J)## !  '"("&,+.3JJPooslkmTSV>=A+(- "%+,&3,$3'!.$+!*)('%#      "%),," ,32+#  '/ '$ $#  +!1./D+0/!&% $$),*1,*2(%0!*#"$#""$&'('$        +  "!  ! +# %((' % #) .*$ "# +% $ + ! 0'0JCMkaoiy6D^4   +&) "  $$!$ %89=ttxy}QWV176)0.-20$))"#"*&%/&$/$!/".("!$&),/.*&        + " $ $!""" '*,* & +# " # " $ (+//+ #  +% ,">-;WJ[ymUe$2L' ! '#  " '*/UW[jqo?FD!''&*+%)+ # #$&(+-*$ ! ! + ! + " " $ " %. 2"4$7$7$8$;&>'?&@$@!=9 5 43 2 1 0/.+ '"  +! #& +))( ' $!  +  $ ) +) %( 5.K;Lk\ovDTo$< +  -'  !%#"&+=@Dikofkl;AA$% $'+#&+"' %%%$"  #%'& "  &0 7 &<)1E1\):W"3P*G!? 6/ ) &(+*(% !    ! +# +$ % ') )% $'/$A,>[Nbzk~.AY+!.' !&!(!%*'+/AEIwz{{UY[389!! ##),'+/!$*!"#""#%(*) ) +,/4!=+.I7Oo5Dd+:Y!0O(G$A$?"<4 -% +  ! './- $  +  ! " +") 9*=XUh}K^x$=(%( / +$%"*#) #(UX[`ef?DF(,/!# #'*%,0&,0!%+!(%!  %)( # +%5&+G6:WCHeOUq[_}hnu|xjyXgJYz?Nm0=Z*F";2'  $-22 )  +$()+,7*8QEVpi|u7Id";)')#  #"+%,8;@kmp~HMO!'*!(+#,0$-1%+0!' %"--& + $+. ( "728TSXwoutYfX%= .&* -'#"  + +& +&   *,ACWk|tnh~e{aw^t\rZpViTfUfTeSdPbPaQaRbTdUeUeXhaqhxl|qv{}dz4Hc . )# + $'1(0 &$ %/26W[]^ae9Y';W&9T$7R"6Q 2N /K!/K .K .J,H,I-K .L"0M#1P$1P&4R+8X/=]3Aa7Ee    !&%%$* $*%(,59;ilmghl/16 !%$*'.'.$+&!  (3&@-5P;F`Q\wozk=Qi'> 4 4'#( (#  # $ $ 0DWe{}n~bsXgL\vCTn#C)I%0P.9Y3=^;GfLYwXf`nkzvh}-D\ / + +"  "&.$*1#("$EHIikm>?D "#)0$,5#+ + +  "   + "95>ZZd}cw>Ri 2G +/%"#!  !**  "/CXf{drQ`xL\rFTj;H^/=S%5J+B$:4/, *(&# !  ! " +# " !$ ( - 135 :%A$/J,:S9G`FTmUd}hw{Sj$7M# +" '!   %-$*0#*..mqq`bc=?B"#(   +"#)0$+4 )&'& +' 82Shwq^nXg}LYo,8N#8"51 )#        $%%%&&&'&&%%% $#  +" , 7#1G6DYKYn`qo|GZr4 ! %! ! '"( #$SWXeeg89;" %")"+ )" ##-+83@SWb|tvFYo/C#%%  ##$8FTkuueuVf}FVn9H_."6 +%#  +  +      ! " #" # '*))*)) ) ( +&$#$ +' +( $  !  " # ! " "$' , 3*<&5G-Oh,S-D4* # + + !# $$"  + + +    !   "# ! ! !"#$%%%%% $ $ $ $ # ! !!      # +$ # # +$ % & ')*** & +  ! $ % # #$7"0E,:P@Pg_nziz1AR,    #%  !!&)$)++/0<@Aeijkhl<:>#"& +/426   " % $" +$#  + % 5-Y:@^Bc?EdAHe@He>Fe\4>Z0;W)5R%/N!-I)E%A <9 62- *%"! $ % #     " + + +  '#';LTiR^}!*G#!)' (*($ !&./9Z\c^]f74?+'2%! %"$(  +5APcpn#/E & +)% (. ++# + 58E^l{yWf5E^(@32 540(  +$ "   "'*..* ' & &(),.. +0 369">&B*D",H%/L)5P0;V8B^=JdBNhHRnJVqN[uU_{Xa}[dajfmgoipktmvmvluisfqcmal^iXcS^}M[wGVqAOl;If5C`0=Z'6S.K$B:654. *& #      $ % $%% #%' $  +8AX|r~4>[) (' ( ' $ ##!"-@AIttz<;D&%!"$'" $ %1>K\iy=Ja +$ ) +( " + )$% # + &+CS`w[j=Lf'3L5 +) ( ( )( ( $ +  + !   &), + ( #" +'/ 8#@*H&3R.=[7GdDPpJXvO_|Zg`ndskxsx~}wrl{crWiM]{GWsAOk8E`4@Z0U#8/ )  +'%# + .'  ,8DZjvkx>Ka%;*   ( #    +   + + + + $*!0!2.%# +6"D!0T0Bd?QrP`^pk~|o|dp^kR_yBMh-8Q$;( #    + +" &#  "1J^$8 + ! +" $ #  %&%#" ! &$ *)?.:R7Fa=Nl?SuH]Uhdwq|weqS`zCPh3@V'2F%:0 *%  $ +  +#,ER]wU`~)E && * % %(!*WV]|>CH! '%%$"!$$ +%6R^qLZr,C . $   &.)23 ) +"-.'  +!%&%$!     " -/C7J_Tg~k{xbpIXo5D['5L'=1' "  " % $)(@DNhs|9Da +0"', ' +#%!#"#/>>DX^c") ("",'"  "(( (7BVfv,:S4  !$ ! + % % ,(0BHOafmbi|BJ[&.=-%    +        +    #("1*;%2C/Ni+;V-H)E".L-:V>Kh`mp|.:X6+&  ! ")&(4# #%-TU]vz}BHL&,1%$&1&)3 +&$  +#%87BV\jhv@Kf)@ )  "#    %+,# "&$!   $"     "    !0"-=/;K>L]N[n`ntnZjJZwHXvSb_oo~IUr!-J 1 +"  # $)!$3* (;=EjjpMQU!%!%* %-$".&)5 -**   $*>P]sfr3>U. !&+ $ (.("  %# %# + +  +"(:;GZUatky]j3@]9 ! + $ #$ .!-%&(*3NOW|6:>"'.%*2%)!/)+- ! 35CXp~KVo":  &/*" "))     &% !     *)<3>QMZmo|uDRo%? #$#" "'+)%(:Ec ' +,.-%   +#%"  %  +&, # %3"+D:D\[e~~lz2A\:*$ # % $ +& "%.7:CknwGJO"'"$! & -) %%:>LduNWu9 ( , ' +$ "    $" #  ''"$ #" *$>8B^XcxN^z#1M)   +!( -'  )+.8[]gilp/27$'#%*' +),;Qbpep*3Q4 +- +#  %+%  & + + +"(&& (!5*3MHQnlwm|:Hd . !!  %++& % *DHRPSW #( '$-(%' +# 6DSl}BLk%C 0 # %*$ + +   $/!,@=H^]i~Q^{8&#  (+&#"%!38AlorLdk{R\|(F+ & +' +% !* & ! )3'>&6MFWnvSd$3L 3 "!+ +#!.!*5(&ZsK\E$ *4.- + % $ $ +! &!.IhyXi!2M 3 !!%$  '( 37<+)))(* +    & +#1BSqat"/V),7 /- *! +!(A`nj|0C_!< "" +(!   )"+$!).3JOTfhf//++)))(*! +  $+)FSfs/Cj6.50 + & " #%=S_zJ]z!1K& ! +(! +($-#+$!',=CH|MNM *(((')" %94EblCY B, +.. * & %&#;DOjyfy3C\) + +(! %#,$,%#(17Md'" "'& '""'*Y^anpq778" ,*)'%&  3ANgrGYz$B)& & +  # % +$$ /FVqQ^w* +)   $"&HMQ_ab++,%##+))'$% ! #9N[vRe+I-% !  " " )>Lhwcq4%!2. +$  + % 8=AFHI !" $##"! $!" "   +&&2H^l`s$6S 4 #   ! ! +!8C^l}w%4J11 & +#   "*! +',0kpr}668(%%$""    23@Wkzj},>Z : # +   !"3=Vct9G^&;." #  # &-% "'VZ]kmq203)$%'"#  &;@Ohvn4E`%=% +   +  -6PYjJXo$1E1 ! $ #$+$  'NRWUV[,*/)#$'"#  '2GQazt;Mh+C)      (0KPa~wan2@U 3   $ $!(!'EIN|~sw|=>C'&*!!(#$&"#   8CXfw}EWr#3J ,   + ",GHYvr|DQi"8 +$  +%& %7<@jlp^`e--2&%)#"%'"'&"$$ " %JVlzRc}+:P/ +   +)CBSpnUc|'>#! !$"#$,05Z[`POU#"'('+*',+%+&!$$ "  .Xf|\m2@U/ +   ! &@>Mkk~es#.F ! # #"'$$(-MNTAAG'&*+(-*%*&!$%!"   &9etfw8GZ/   +   !  !;6Daexu.9Q& $$  "*%"'ABH77>%$('$*(#''"%&"$  +   &1Ern=M` /      + 3,:V^q;H^0  %&  !!$,%"89?ppv007! $"$$#(#%'"% + "4?S}wBRe 0      *!0LVjLZp(>  %'  #!$,$128aaguvz++2" ""($%'!$  +,DQdHYk"1      %(DQd_l-9O +% #' +% #+!*+1RRXklp,,1   &!$% $  (8Q_qO_q#1 +"    $@Qcmy5AX ) #'   (!(%'-IJO}}bcg++/!  #$ #  +(3D\kSbv#3#   + $@Rcx>Kc." (!(' #)?BGpquVVY$$'! "!#"$""'"   +&/>ShzSaw#5 #   ! '&DL]~Tb{$<  ( !  $("'14:[]bMLN"!#"!$""&!$*! + +-3F^pP`w#8 + #   +$" +!-(FGXygu*/H +) $  *' ''*2KNTJHH! " !# !%#*"  49MfvPax#9 + # !  +#" ,(FHYyl|,4N ++$ !*)"($(0DINyyyECC " %!*" + !&;CWp~Pax$9 +# !  " *'DHZyu/:U! $ -#!)*% *"&.>CHnnn<::" %!)" #-BPc|Qay%: $ ! +  " *'DHZy7E`(' .#(+' *"*48>|~bbb421! %!(# &"3H]oQay&< $ ! +  " )'DJ\{AQl 2* .# '+( *%*.3jlrXXX,*)! %!($ ''8MgzP`w'= # ! +  " ))FL^}M]y!=- +,# %*()""&+[]bNNN%##"&'$  +),=RqM]t'<! " !  + " +*+HOa\k .J /)##((' %MOTEEE   "&&# +1AWzIZq&<! " !  + +# +.KSehx,;X 3'# #'(&"BCI<<<#!$ "$#"-7G^yEVm%;! " !   % ,"1MWit;Kh9&# #''% 89@ww}{}~656" &$(!"!  "1=Mds@Pg#8 !  !   ! & ! .&5R\nL\y$@ % ! $&&$008jjpxz{1/1$ ")'*    $ 3AQgn=Md"7 !  !   " & ! +0)7T^pUe)E $ + "'(&$,-4ccisuv,+,%"#+)+    '"7EUktdp\idqxj|:Kb"6!     # '" 1+8Uas]o/J #  $()($)*1\\bjlm,+,!)') ##" +  (*?L]szVc~>Le1=V%.H &B%+G6=YQ[wvfw3CZ2    +  # & ! + 3.:Xdvp%7S +! +&*   (*"!")PPUade,,-&$'$#' &%# *(3HTd{vGUq$1K 1 " &'BGQms~ar,,   $&#$()'hhoWX[&%)!"*',%#)##9@Kco~P[w/ & )+ +(!  ($?NYuv?Pk*A' + ""  + !)2MXgOa+F 0   %($$) ", __fTUY%#("#+(-&$*$ $9BMerKVq. " +' +& ( +# (&AP\xn5Fa%<' ##  !09TcrUi!3N5  %)$#*"$/WW^TUY$"'"#+(-&$+$!!$9DOgtyGQl. $ +' # %! # +.",HUa~fz,=X 7'" +!##  !9B\n}\q(9V$;  $)$#*"$/RRYSTX#!&!!*'-%"+$!"#9FQiwr~BKf , % +& +" % $! # '5)5R\g[o"4O 2&# +!##  " !BLf{ey0A_(A# +"(%#) "- LLS¾RSW" $ )%,$!*#!#$9HRkylw;FcozEYx#>,&# + !   &(P[vt?Pn%1J,   "$#$% + @@G}|OPT! +%")"(!!$$7HUl~hr8>X + $ #  (- % #">>Jgv?Qo 8*%"      (+Vb|zDUr(5M0 !  &$"" ==Dxw}NOS" " (%!!#'9IVl}`l08O " #  +%* & # &%AEQm~7Gb 0(&#  !  & 1YfN^z,8Q.   +$&$" ;:AontMMS% !(#!"!!+Vv\m2>W , #)&#! 48=^_dIHQ%$ +% #.>N\nQ^v#.D!    $ +%" (#0IS_z|HWm&>' +! !"   $ " *$=BOics6BZ-")& " " 25;Z\aHGP%%!,%$/>O]oN[s",C"   ! % % '$1JVb}m{8E\ 7& ""$& ", -HQ_yhx9E].")& ! #!039VW\HGP%%!,%$/>O]oLYr!+A"   +" & % +&$1KWdbn+7N3& "$ +)) #.(6Q_nn~=I`/") %   # !.17QRWIHQ&% ,$#/>N\mKXp +@# +  ! % $ +&$1KWcVc} ,D1 +* % + ,$ +03A\o~tAMe1 !) % + $""+.4LMRKJS(% *#!-Lg}yEQi3 !) %  &$"),2FIN}MLU )$)" *9HVhzLYq!,A#    +$ $ & -FQ]x~>Ke1 *+ !  ' *(%"U)%,$  + %()+,E\kKXq 6 !) $  ()$%(.>?DvtzSR[#",$) " &5BQbuO\u!,B#  +"  ! $# %)CKWrap$2H +  !, ' #!!$'* +/$2LgwMZr!6 !) $  (*%$'-<qouVU^'&0# *'    -6DUlzdq:E[ * !  '.#86C^nzbp(5N$ **+( # + /%2KN_yVbz(=  +" #$!%&!$*78=pntWV_('0# *'   +-4BTkyjv?J_,   '.$5/' ! +" + ##  +5Igsy^j@Mi,I, -4 +01683+03 *4T_xWc{(>  " "" $% #)68=pntts|21:%   +   + ,,=IWm2;N $ & +"## ! !%, % =]kl*rovxw43<&!   + + *'9DRh=GZ* %   +# %" !%- $ 5LZyWk(E &!! $  +  $5]fz{bs@Om(5Q$@/ '$ % +& (** &! % !  % *$+BZc{Uay&; + +" ##!%'"%+8:?sqwyz55?'"   + +! (#5@NeDPe/ +# +  "' +$  #-"->Ml{FZz5 " +&)#   (1Cs}rWeCRr0?]'C +3+ ' +% +% % % (-. ' +&. !. ' &#^ * %&,-&   *AJ^mxP[{8Dc%1O%C9 /+, / /, & # &, /,, +1))3-# $ <3B^bpR^v$: + !  !#"$&#%+9<@rtw27?    % %   +*65DZiv@Kb!4 + "'# "/!3NPg{=Oo<# ( ,/.' + '/6IdmiuU`y@Jc)3L";/) % ! # +) , ,)% %* / /.*$ &-124 ="2R?Oo`qKYp"6 # +#  + $! "$*;?Csvz6DK!!   & ($ +!*65@[Vb{$+?  " +     "0(A^iO]~$0N 3 () +,( +& % +"  + %!(;GNa}}ftQ_q>J\&1B-    $ &# # $% * 0 2 0*"! +)05 +>,O5Il\oyDRi1 +!"  +#"#(-ADIx{GMT )#    $ '# '32=X}gs)1D + " +  $ +" +$/JWrgx6Ed!>, &(($% % +"  ))0AKRd}hvQ_uDRg6EW#2C%6/ &   $ +% & ( ( ) * )& %%( +- 1 0, '# "3"3TCUxattAOe/ !  +##%*0EHM|PV]!'0#   +# % ! $ +/.9Tux/7J    +#) $#>Ic}tM^)7V +5 +&  ! "! &) % '"):U)6M,B 3&   +  !#$# !  # ' +)' # +"  # $ &.;$2O4A`DSs^nvjx9G]-   +"").1PTW`em,1;   #" +!,&2NdqQ\r#+=&    $( #) 7NB\ryYj,;X$@) (-'  !&+#+=AGZW]tho~l|XfGRo0H`08T&0K&?2' !  !$ * +(" +  !)./ , ) $ % - 1.. 19)C%6R8JfQcqbp4BV-   ""  +04Y]`msy5:B   $$# +$."0MVdNXm#,> + +' '"" " $, # ")=Sg}bp#1K* " " ('# !    ! +   "+";37OEIbOSn^c~~o|^kP]tANe4AX$2I!7( +  #*02 ,#  -"4 )!# ' +0!6!74 -(( +% %3)D2B]K\wdv~\j1?R-  + + !#$  +.26`cety9?G  $'(% &/!/MP^}cn/:N" ' '$% "& 4).?Qer4B\+ ",+ +&"   $( !  +!8),D6:RILfX[vcfpszslybnYezQ^sHTiZEXsewVd}.DL $ +) +((/ .KJXw|y=Ia)%%$% "&6. %)8J^mFSk2  (( % #  +)$6#4( %)'   '+4"%:2,7'+D48QCG`QUn]azgknrswtyuzx}{|}{vo{gs_kWczQ^tJWlDPe=H[4?S.9M)4H$-A(<#71,++ ) +&"     !  ! $ (* )% $ -- . -',8"/I9IdI[wWii}Q_x+9L +   #"$&  58S.6J(0E"+>%8 2- ) & +%!      $ ( &"  $ ( (&" + +& *'& % " " &.$=-:T=LfN_ycwsN\u)7J + #"% '  7;=moqHMT +  # +( +**/(F=Mmm_m ,G ( #" +" " +', & )9T_rxIRg"!4"6! +   +# # +!.1' +  +! #&% + (& #%')*++.0#3#&7$(:$*<',=+.@+0B,2C/2D/2D.2D,0B+/A)/@'.?%,>#)<&8"50-) & $ +#!! #  +    +$(( +% ###$$##% ++ -( # +! ! "' 3*E/?YEVpapsIWp&3F ' "!%")  ;?AsuvUZa!!%*+,."B6FghyKZv'C $ (*  "  $1:Klw~JRh"*= "#.0'   !   & +! #$$   +  +  +   +'((' !  +  +      +    +  +     +   +         +" %& % +"! " (+ ( ( +(%"!#' ,35,(, 17*D,;UCQm]mww?Mf!-@ "     &$+AEG]bj  #' ( +& +' +;-?`ariy.<[ **, &     +/JSeZav,3F+%'#$# + "&  $   !" +  ! !$ &))' #  !&&!  +        + + + +    ! " +#!  " % % % % % & ' * , + *( " # '.7*F-`^qARr7&* ))%  +   -5G`i|dk7=Q"4)# +  + +  %&  +#.!5"8 1' " " +! +  $ */22/*%  !   !%'!) *#       +      +  + ! +$ $ $ $ $ # !  +    !# & *, )''&% !" ' (0"/L8GdJZwdthv0>W'9"   # ("&+NPQgnu ) #++ +$$ +#D7Jmh{]p)L1, % * * + "-@GZpygn9@T/ "$$ !$! !1-8M@McAOf4DZ!1J5( +$  +#( +* + +( $ !    +! " +! + +      "!     + +      +   +! "$ & ' ' & +&%# ! ! ! ! " +! +  +  "')$ !#&), 1 9(C)4Q5B`9FfFSseu|^l&4L!3 #  %#+#&+!UWYtz'/9 ! # " $3 1RI[~vy0Dg A1#(+  + "%  !*0BQZm}hp>EZ#5  !% $ + +-+7KWcyxzj|Tf5Gb/K#? +5) +$ +$ #!  !"!           " $ % % % $ $ +#!   "" " #&& % +#! "'*'&* 2 ;+F%7R4GcGYw[moyTb*A- #   %%,!%* $\^`DLV&2+"  (!?2Ef]pVi):\= )& & " + #*&  /1:LWbu`j9AX#7%   $ + '%  + $0CLYnpYnF[y3Gf 3P$B 81 )$" +$ %"  ! #"        +  #' ' ' & +#"  # # %)+** )+1 7#=)C.H"5O,>Z8IfDXwRfdwvKYw 8& " +    $$+#(!$'dggjr|=FQ$.< ( + +$ 9%8XM`v~HY| 0O 4 $ ""$)(   + /.:LUav^j6@X5 +# +  !*# /@L^n{x`vF]}4Hi(9Y)I;0 ) ' ' $ !   !#& ( '" ! +! " $ & ' ) )) ( %# ! !% ),04=+I#3Q.@^FZwUj\qh}wDRp 2! " !  + #!'$&)-knnir}GP^'2C#6!7%>/J2DbOaqhz8Hg)F& + %#"!#  -)7KO^tz}R`|3@Y%< %   "  $4>Ndoyh}YmIZ{8Ii(8X)H"@< 72,% +   "#     !!"##  + ! " $ # $ % $'+..+ *-4 ;"B*J"1S+;\7HjGYzQc^ry 61,( $  # '+ / 5 <#?)E(6T3?_5Dd;LmFXzQd\newoy~3B^*     " :<=vVb'/H   #&*(! #&:6Jae{gz@Pp+I1+ -*(#  *;?L`gusf{\rQiF^}:Sq1Jg)B_"9V1N)F#@ <98754333210011-,17#>)D#.J)5Q/;X6C`=Ki@OmEVtUe`qgyp~o~*9U&    !# #%GII~KQj 4  +"&&+- ( $&<6Ka^u|Zm5Hj%E0 ( &()( "    69Ddiu{smgawYoRgMaJ]}H\zGZxGYvHXtHWsGUrETpERpFQoGRoHSnIToITpJUpJTpKVrO\vUa|[g`neskxo~u{_n.J #  !  &$ (*,TVWho15K+$# ")$ + +(-##.)?2G^Sjui}H[+>_$D/.. +#   %" '+6NTa~}|{{ywwyz|~Ud%B ! "  ""*$ $.02\]^MVn$+@-(&(+  /,& +) * +,#:'7N@QiZnx~Xk7Hj-M;0*, + " +! "  !!'7DM^p{IWw;    $$+$!569kjlx@Mf)?0,, '  .!50 &!    '$94DY[muZh9Fbgw`m%0J * ! + "'!) !' "[Y[qAPi+C* *36)*/)#     !."0@4CUBPgP]y^lp~zasN_>No(7U#>52 ++* ))) ' +#   +$,/+#) 6"0LCRnn~Q^z&@&"!!&(%)(*hfho|IVp$1L80 + +' $ &+,/-% +  $ % ! &0%; -G*8T9FbKWrXdaojxquxwwxwqkzetdsbq\jQ`~BPo2?]$1O'C6-+' " "'-0, % " $   ( ,&,!0KLZwzCOk5 " #"$# /.0usuYe6A]#? +* +% )03.-+ " + ',* %  + + ( .4";)B#/H(5M.;S5B[:I`>Md@OgKYsRa{L[tBQi:Hc4B\-;T"0H#; +/ &  #)+&  $,/*! $  '& & +/$2MN]zx6A]+  +$"!868it@Hg!? )$ ',,* ' # +! !%(*)&   +  ! # # #$%&( ,03!6&<")? &:!652 -&  "&) +,( +  +" *- +' " ")%@5D`^lnz,7S +$ #" !!A@BvJNn#%D * ! $ $ # &*+*&"    + # % +%%#" ! + +   +  +&. * $( ( " " +) +* # * +- & ''CERosbo%0J!" #"&$)ONP{OTv*.N6 )! '-/,% +  !$%'( ( &$##"! +       !# ( +) '%' )&  /!<%A*5QP]y}Ub})B  !"$ "1/3]\^ciEIk(*M1& + & (*)& # " #&'%# # +$"   " # #! $)& +" ! + !## !  + !&( +) +) (% ! "* :*5QCOkdquGTn";  !$""!&==?lkm_e>Bd(,L >6- # "&)&      " " " # &'%"    !%&&"   +  #&'% ! &5&A&1M6C^P^{s`o6E\3  "%! )(-LKN}|~~`f@Cd*-M8  +# % $ +" +" +"   " +$ % $ $% $    +  + #'(&$ +"   "$ 1*8RDQlWdmzSa|+9P ,  ' ") //3YXZouSXy:@^%A0 +($" $)' "    ! &(' % + " + ! + ! + ##         "((+!92?YYgwGSn -E +( !(!#( 668fegtcnU`zCMe'3H1"  "" ! % & % %),* # +! + # $ +!((&  +! ,";(4N@KfZgxx6C\5'% +"  %#)><>wuwzSbv/?Q&6$    #+-* & ') ' # % + %&% +! + "*4$=#-F4>WHQl^j{m{)7P)% *  "*(.#!'"GEG¿Yj}2DU&6#  '/0+ +$!!"!$ ), %! + '))().6%&@,,F/3L:@YHQkT_zcnx]j -F $ & +%$("!%*)-USV|H[l2A( ! *12 ,#" ,5 !>"&C:/29; ="#@')F13P>A^LOkUXuZ`|goyJXr$<   $ $ ! $548daeK_p0?&" '/2 -# ,$(E8;YEGfLPmEKh?C`AFbGKiKNmNQqRUuY]}chqvr7E^2 $' !?>Broq=Qb"2! ! +# +/ +#!!>GLjeiuyYh%4K -#&" JIL~j%:L!  ! +& * (" '.3PgnAPj%< )  "%""' +  WVWYp'9 "! $ +#  +:A\~|*9S +/'  + + "!#,)).  '$(ifhRfz . #%   +   +,?Gbfu(A((    + "&,)*. 3/2zwyP`v*#' +(#  + + "$ /DNhO_{5& ,%  #'%%)B?AJWm#( +( ) & + & ,#7O\qx9Hd+$/ )" "!##!"WUWAK`&! % ( #/&7"0A\k}jz-9U! !1,!  +  !  .*-hfgymvhskwwv9AV!  & #"3".@-;MgvZj#+F-)  ! "%!&=9<}{|lsU]qI#0)! &2"0NP]}lu3;N#     "'<7B\r~Td})@" $# #,*%#$"&DCG\]g +  " %;7Ddcsgq/7I#      #(<6C\rsAPg4 $*( %+(! #-+/YX\EHQ  #  + ! %#! +0)6VVfbn,5F#    ")<7E]t^n.DpotNPW)#, #   ( ++ +& (8*8Vfur7@S  %  %82AZp:Ja5' +   '+$!(RPVWZ`')3)- $ ! * , ')7$0M[j{KhJYi! + + )( "8FYtM\q,>,    "%$!109]\d55<&&,- #  +! +" +-4?\wSct' ' + )*   -2C_x4BV %"  )) GEOAAG$%% -,  ## )(4O_n`o!1##.  &(#  %!1Mast!/B +!!+#%/%  ^]fSSW%%+  ++  # #&+DL]xl}#3D, +  + +""   #*FRd[h{%6     &#&."$, "!*zzjim0/5)) + $ $ #!9:Kdt{8HY%3 &       %#>ARouo?K]-  +    #*'*0%87@@?D)) &'  " -$3LasRbs0@#   +!"  & +3(8U[lM\n"-? $  $ #(,0,-4SR[RPT * * ((  #%8Oa|k{-?P#  +  +$& #)+"?@Rr}n}0?Q*   !&%(,0@AHsr{cac"!, * (( + & +'AOj@Rd *      ' )', '/,<\fwVdw+=! +  !$!%)!&*-2YZausv((,"#",( %& !(4=WWi}&8   &* +* /$#(HL\~yv%#*#"+$ "" ',1Jo{l~%6K( + # ( * /$;3DfZmXh~'7H +' +!!%%(, "&!"&GGKTPU2/5#!(  %"(B]h;Kb$7"  $ ) +. +&! 4.O:Mpvt;L`'7"!%')-88RgoXb"*H )( ,.1% *94 % %#@;Mjo~JXv -I-& * (%#  #$MOOuty>>D + (!, +  " ("*>MUl@Jl<1./ 4 ( ) 7." .+H;Olez\k)6R 1 +" " +& +%  !$  $-01lmmXX^&!#. !  +(25?Vcp,8\ B30 +5-  (/ +%" '+.4"?,>[ZoBNj < ' +" ##  + &&),.FFHssy$$+ %"$.    !+ +!,ChtTd-;`B54 0 ' & +%  & +1 4 +0, (5+>Z]scp.9V 3(&$   + )'!;<=jik87? $ "+  +  +$+#0LWpN`%6Y @20+" ! *0 0* $" ':)^0 +$''- %  ! +' ) '#-,J>Qpcu]q>Qj!3J 0# +,- +. % $# +"%*)!206RQUFGL%'-" "% %!  !"Oh*8P%; /*(%$& , +# ++,;P[jVm,@[6 $ "#" + + * ,"((-edh{z>>D""( ( !) +( "   +' 9FTpxdzCYz+?\%? '& #&(( % +#"$ ( *41N@RogxwduJ\q2CZ,B , +#%$  $,BIYps8Li!< ' +" & $ +& *#87:UU[)*/!!'"&( +  )/%++8SZhWn/Ab&D7 .   + "!  %%$# $ +% % #/"?+9VFUqcq}hyL]q7H\)9L /B%9 +-#  + ##! +&$+9D[sUi.I'  +" ! !$&$+YW[pqu68;"#(* ! + $/.'%!:;HduZn&;Y2&"  + ! %* &""" )9'3OCPl_m{hvIXh-Rm'A +" #%"($87;rrthgjCCG #+#.$ + + % */'>APjfv1?Z-  ! +''   +    #' (''( , ,( +%"+&B4>ZJVrfr}t`k~S]oAL].:H *8!.' "   ! " $ %#   +# *. /*%$ " 6CVoVi#3M+*"1 "!'&',QPT[Z]%%)$",& $- +)*%3Kdrhy6Fa3 +      +  "'(%%( & !!  ! 0'B,7S7B^@KfIVpVc}htxlv`j~T_qBK]3  !%$ "!)8<@egjNOR "' &"   !%"(5I`owBRm(@$%-'  + +#$ +    $00>BBQ=>L()8#  #%" !(.* $ " +& * +* & $* 1:*D)6P7D^ESkTa{eqmzu~sybhPVmAG]3:N'/B$9/* %  +  !$& " + + +  ! & ( ) ($ +* 6(B&8SThN[v*C* ((  +!"*$+ %QTXoqr58; +$ )&   + *=MaQay /F) '"0(   &+'  + +%(->NRdmqznsIN`$5 +&/2231, +$ ! "' .5%=!,H$0L'5P2@\?LhHTrP^{]ljxs{xly^lVcOZxBJf9AY4;R.3J#'?4+ # +  %))' "    % *&#" ! ,*D0B\CUpWkfq'0J +" " #)( + '#*$ %6:?sv{OQS  #*#&.'    #2Dj{hx4CZ2 " '&  &+, # "1*2IOXnzW_v2:P 6 &   $%&-1. & # $ +!   ' +19'B'4O3@Z=KeGVqPazYjcuhzo|zsjv`mWdMYyBNn6Cb)6V".M%C0 % $ #   % ( ' & & ' ' & "  !!#+ 4&@(:TGXtewzuAKf-%'' #  #+! (-2Z_cnno#$( !%$'-'     0KZk{qCRi+A*$$ "  +  &' %  ##<;Fa`j{dn?I`&>% !%% + ! !(.1/* '&' & % $ +" !!'+ +/4!8%<)@-D 0H&6M*:R.>U3CZ8H_;Kb?OfETkJXnLZqO\tQ\uS_wXcz\f~\g[fXcT`|P[xMWuIUqHSpGQoFQnDPlBMk@Ki=If;Fc8B`5A]1KeO_yduyLWt",G  %($ +!!((- BHK==@!&# +! +  +%*:JWgyK[r#3H2 * ) &  $ !  +""<>KhkywQ]w6?W$'>- # " ! +    "'+,* ' ( * +)'& % $ # $ $%&'&&'((((((), +/ 0 1 24 6"9%;'=)@+A!,C%.F(0G(1J'1L$/K -H)E&C$@#?!>!< ;;:74 2 +1 0/-,+ * ( (%$ *-* * + ) ( ) * + ,. . ) " #'('&$"##*"8+6MDPg]ju}PZx+3P1 %(# "%,#,1#'&03hnq\[\113!"& + +! /6EVkzfw.=T/% +*- #  # ! 28Gcn~zdmELb+.D3( + + $& $ + ! " ' %# $ # " #%'* +, . + +''& $ # " " ! "$&'(())*+ ++ -./10145443 2 1 1 +/. . +.- ) +& % +&%#""! ! -50. , ' +# """ # && +#! +" # #%), 1#:!/E6BXNXpep{Zg0:W7 +# ! %(    $$-23<@U^a{{{MMO014"! +  +  *:SauVf~+? + +&, "( ! %#0M_pt{UWo==T''=)&)* %  '++ + * +* ) +) +* +* + ,* ) ** &# ! +  + + +   !#" !       +   ! $ % % % +% # "$# +# % ' % & & # "# # +# & ' ( +, . - ++ ) +&#!!!$ +& ' ' (+/ +10+ % +$(4&>!1J7E_N\vkxq}>Ig"? % + & $( +    +&04R[^nop?BC"    ! *=J]ouAOf0  & & "'& # +$0#0JL\zbc~CD^//J"#=1 ' ! +# +" " " #$ ' ( * +* +* +) +' +% +$ "    !"# +$ & % #"!! ! !  +  +# %&& '&% ' &&)*)*+('(&&(++ &#& +' ( * * + + * ) ( +' % +& ( ** ) +& '1'B,AZ?SmTfq}HSq)D , # %% !%  +   ?HLUWW(*+  "  "$1DETiwQay'4J"  ('   "- &-3@XWg~fhHJh23Q%(E;1 ' +"%& ( ' +   + ! "$&''&&%$%& % % % +$ ! #&&')))+++, ,+(&'((''&%$ $&&!!% )- 1 4 4 2. * +'$$$% &+3'C+@\H]yh~~P[x(B # '-) !  !"" 17>nuznppSrQfh|}]i1=X1 ! % !  $)$ !'.JQW}BDE" % $+& + ( $ "7>NfuARm-F 7)!    +!,+&>LZt~gsS^zHVpANh5A['5M,C$; 5 0 +- *&#    !## " " +        # % % +& &&$#"" ! !   ! ! ! !#$$##"" ! ! !#%)0 5 9=??@C$F,N*7[/=`8IjUej{tes-Qb|l~*;W 3 +. ++$ $+ +% 4@Xm{}n~\nM_w>Ph1D[%8O,C&;3 ,&"  +  +   + ! +# +# " +" + + +       "&0 9B(M(3W1=`7DhAMrKY|Yhjyujz;Ie: " $)'&%#  (,3ehpNPQ!$'"#&*"'   +"$# #/>Xi{[m*F &' +* &   +# & ' !/S^xp`vPf?Vm5La0CX*:P%2H"+@%80* ' +% +% $#!     #"      "$# # ( *.5"9%=!+I(2V2>bALqP[_lkyy_o2A]'C +0&  + +!'*#-!*  $)OSXwyz68:"&!&&   , ,"P.;M#0B&8#5 42/ - . +- ,-+*+ + +) +) +* +) * -.034 4$:!)?#,A%.D)2J.9N4>T;D\BLbIShQ[rT^vXc}grs}yu2A^ 6 / 10&  +#&#* %'+.IMPPRS!$$+$   -/  -'7RP`{q>On :" "()$ (+ '$ )2>I`|vqlzftds`nP_sCRe@Ob>La9E^5A[2?X/;V-9U,8S*5R'3O&2N)5O-7O,7N-7N-7P-8P/9Q2] 7 +% "&(',, %%2'1HV`y{xurn|lziwhvgteqboaocpepepfqgrhsjumxozq|utwq?Nj,G7 +-$& ' #$ )$) &+*FJHtyufhi?AA#%'"(!%-'#" +!#%''61@YiyL\}.M 6, % % %& + +$%!8Vjxn}(8X0 + '" &, +& ! $$0HutFPm(D( !  *$1!+#+$+0!  ,1-MQK~:9< $%"   +!((&"9@Mhn{l{)8W/ '" +%, +, +) " #&)5MxkwCNj *E+ $ +(  ,&2!*!)$*.!.20KPJvyrùede113%&"   # $ +% ,$.HMZvp)8V )&%" $ &' ($& +.:Rwfp;Ea&A , %) &!  #%! !$!"(-*KOKtxqXWY"!$!#($!      ++*6P\hu+:W )$ +& +$ +% $ $('( ./@&&)%&)#&#  +   #73>X]hy.Sd}n{HTm)2I-  + ##"$&"*-2IJOoprTPS)')%&# +    !#6@J_t~AQi&=($( -( !# !8BTl~an6B[$: (   + '*&   !'IKOz|{}KIJ&%'##") '"  $ ! "(;HTh}N]t#2I+  "*) !$ +  +3+@XcxXf0Oi"0I +) %%##&&#&!$*!(!"+/5SU[cbc<;=! $"$($*# *#0,  !1CQbyR`r*= +#("#%$" &=[kap6EZ+?/   !%$!#)#+' "048TY\qpqEDF%$' %!   (!., +9LXgp|p|(6F ' ' " +& %""! ! 5=Kao}jzO]q5BU'7) #  +!"%$).$*. + 046bghihi<;<  "&&&&# &(3@FP]fp}w7BP%4$2! +% % !#% +#/DO\q{Wh{5BT%6&    "# $#&!  *//Z_____333  #))#  !&%.;IR_hq~ajw=FS$.<$2!! $! # ( +%!-0 -" +  !! + !!'$(-'*/#&+ #&*=ACaefKOT(-2" &%*0#(."  "'&  +(%   +  $$   # &$&$: +& +#$   !"!%%(*&)+ #% "(*-FHKjnotw{INQ058 #(#&*'+0!$) "#*& + "*"+    +  *,&#6BPi~|cvK\s4EZ+>$  !'!$' %'(-/0:<=QSTuwx}RVY/15 %!   #$ +!*!&.##    +  -!4*";P^yoN`z1D\(= .)!  +  ")#("$&%()#&'#&&*+,:9;TUWy||{}GGK##( + ##*#!   %* +# +#.#6-  +6QfszZk;Jc%2H2 $ ')& ! "$).#'* !!"# !"*,+DCDjikutvFFG(*+ !!$%"&'!#&!  +  % -,+-. ) "46D_crap>Ne 0H / +&#."*4'-6(.4%)-!%##$$%%"""BCAwvv|||PPQ557*+-"%&   +    " .#2(   +( * $& 96D_lyhzL\t1?W&;*    $($+"'-$(."%( %$#0/-766FDD\[[_^`>>?%&'"!!"   !"  +)/ +"(2 ,%'$>DQmudvIYs0@W.C 5(## +$ $%'&$ ,*)CA?ca`iii?@@())#$$#%% #$! +  + #$'+$    " +!  +$ * )( %()DDTpiyg{N`|2A\)C 1)"  "*!+$&#* '  "#%)**.-,754NLKkiglkkKKK555$%% "" +  ""  + + !"%(& #(%@>Lhiyz`s?Om,9V/H8.(&# +#&%""!%!,,+EDCecc¿|||UUU332$%% ! ""$&' "  "      +# +$$$ # +" 'BFUrwdvL^|.@] +3#''' +' % #  + +$+$  ')+023(*+ A?>nlkWWW566!"!! "#   +     + ! #& & %# " !,*FBNmo{dvGXw)9W!= - & &&&"   + #%*/(,1 #(  !!-..CBA`^]^__578&()!#$!! +   "%')) &$ !  " & (-%C>Iho|z_oDTo)9U">- +,2- )"    $##"''+/,/2$',"##JII~|{npqILM,./"     #&()( & +#! ! " $*-7".KDPmp~s\gBNl)7R"<, +% +$,/'# %&%##%'&!!%&'*,-.0=??^]\}MOP')+ !   !$$% $ +# "! !%)-++ /'C@MjjwzlwWb|>Ic)3N!< +. $ " +,0 '" "#%'( )'# &()>@A^]_^ad?BG,/3!! #(!  + +      !!! !& ** % *(F?Kidrn{]iMWp>G_,4K6 +( " +! +! +! +! ! +%+*%#$%$ %#&'')(*+578UVXzy{}OSW(+.     + +  +   !#$ + # + - +*.6'3POZxuZg>Kg/;V$.F1$ + ',--.-,)))!"-#%. "))&(<:<^^_VY]259 $   "      ! +# +% +% + " +,24 +1*"-$.MS_}o}S`|8C_ ,H 4*    $'*,/10,)((!)!)##!#;8:NKMmjljns>BF"&+! % )(%"!  !" # % +$ +$ (, *% $(,-*+:'4PDRnm{v`nKYv;Hd1=Y%2N&A5*" %('$      %,,&! !%335RQRywwsw|NRW8<@*-5"&. *('%"   ! # "! +& + +' #! $*-- 1 6&B7C_^khwTa@Mj)6R#? +2 .,*' % $ "  ( . .)"  +    (+'$$#&*025GILiikruyUY^8;B #-&%! !!    +  &* )% ! ! +# $ '+3#=,8PKXokzjwSa}CPl8F_0$   ",02<(*5$ "%&#      #'8-:K;IYHWiZj{gxtuitahY^tINc6Ie2=V'.D %92* +" +          +&)%%(#!-'&0+)432Jd3AX)6M*D#=4$   ! $% $ +!       +  $%%" "! +21CBLLKUZYckjstv{YZaFGN78@()2( "%'$   !%&$ !  +   !#' ),1%8$.A-9M1?T6F[@TjJazPgWmbxls{{ri{_qWiO`HYu?Ok7Fb3?Z.:S&4M-F$=4 / /1. +)# +  +      +    !#()'%&&$! !!(!&-"'.'*2<(A*C,F!.J$1M'5O)7Q)8Q)8Q*9R*9R+:S+9S+9S)8Q(7P'5N$2K"0J .H,E+D)C)B&?#< 9 5 0-) # #,2 +-*)() + +, ++ (&$       "&&$$%)!+ ", )$  +    $(*-25:=7:7242-/-'*' %!! !!"""!"" !$&&$"!#$$%#"    ! $$%)**.01599=<>BABFMMQVUX]\^gfhsrv{~rlnibd_Y[XRTQLMJFGC?@;683/1.+-*'*($'%!$#"  !!%%"(%")#"' $ %%% &!&&%$" !"#$% $$$&(()))*++-..143599;BADMMOYZ[gfinnqxwz|zzsnohfe_^]XUWQOPJHIECDB?@>;<97:5382040.2-,/++--+./*0-*.*),)$*% %!! $##(!$'"#'##("$'!#'"!' "&!$$"!!"&$%*%(*'(,**/-/313777<9;?77:68:89;98<89;9:<;:>9;=9;<<;?::=:<>HHKRQURTUUUXZZ]^`bcfgkkopqtuwy}|}~}|{|{xzwvxvvxvvxwvywwyxxzzy|zz|{{}~}~}þ¾ \ No newline at end of file diff --git a/share/qtcreator/examples/15-Utils/five.bin b/share/qtcreator/examples/15-Utils/five.bin new file mode 100644 index 00000000000..4cfe3920579 --- /dev/null +++ b/share/qtcreator/examples/15-Utils/five.bin @@ -0,0 +1,999 @@ +y|ilqY[aMNVBDL:=G<@JCFQIMVOS[[^flnvihlCEJ26;(+2"  +  #%(!%016>NQXqt|{~_aiMRZKOR~ikqGJQ47>*.6 +"  ')% "$".(/99>ILOYdfpBBI#  + **  +# !!  3:8MSN}~ghnBEK%)2 + !   +  "01PfEZqE[t?Wo1F^'9T*D +4( "" +!!   (08bhoBIR$."   !  . % / 8"="=82/,& "& *,( +  !*.8`enyx34@ $'$$ +"$0BTcwrvytYn8Nj 2M9+  ##)& +&6=F{DJT   " ! + *#:,E+:S5F`;Li9Lj.B`#5S#>+,) #  + #+ " +&4;DdksEDL +  ! .,.AS]o{|\l8Ea&C* (- "  +4:Dsx?EN  $%    ,(4ICQgsyvgzUfK[v5B]#< " # & #    +%-7^gp^\f''& + 8;Ngk~cn@Kg4 & (+& "$.5?hmwQXa$++) % +&%7AMbr~[h9F_*@ , + "*(&#"&0=BKuq{-*5 # +  +'7I\lyp}@Ld'> )* $"&/LNX50: ##/  (;BUnyqX,  % $7>Eqx4:C& #!# .:F]{t=O_0? )    '0\`hLIQ &4jrq)7T," / +! + 4X)#'  LRV?DL# +0 &0LXp5H[ +' (# %)dgkQNV"$'#=U]zn~*>V# '-3adh`bl!$. '8C\>Qh"8!   6Csv|%(1&   '/7C\bt 0E"(" +KPP}* +%! .LXt;H^" ) %!# (ST[W[`#' &=Wc~M^v5   !&*TYY\_j! ) +$ 9kyu.=S %  +"%!+zz9;B' +#,9Sv3D^& + +ILZ%"+ +$$/In{ 2&$&$$DDO$&0 +  # !IUpm/H*  $.  ouv:=L&# % %4A\EPn(+  $) ,GITVYa  +   !2ftRc}!9" ,! @EG(-< "  +0FSmCGux(!"'>esdi')   ! -cjtdfn$ '1lwDQj  + 049fkmnq " #%"+Dn}=CZ ! "- $3:GNPX  &!+Dgv*% &)/DHLcgq  !$&1Kv'0I -' +*CJX>@G # $&1=V|)8P )  $&*0x|Y]h +!&)7SU_x#9 +! +',!#2nv24;  !# /?KfO^x,A#  VY`OS^ + $).>Y=J`( * % +7?Lhhm!#*" +  "!9Ua|y3BX +( $  + 36 +  # +ZZ^@DO +  ' , :Jfz(7L ( # *RZd=>C& +*CKf{3?U & +?>Cvy~dgmTX^HJTABL>BJ5C>DHLPU[aelqvv{<@K + + $ ,!@PlPbx ," /)2;159# 0Yb{M[r $ 217yw|}~RSWFIN;>D,/7!#,#!   "'./398:@MOWgkp~;?J # ++!CRn0AU'"!0 & !*QY`svz'*/""3lxjx' +# &%+\Z^jln78<      )#,"    )/4=V[dz}=AL" *DSoZl.C% ( * !")bej!)! +!7|(>1  ;9BM!) BRm6F`%"%%KVYFIN!)  &/FO\s * *(+`ce469! + + $ +  + +"! # ( (#    %& && $ '$)2;?Dcgj@DO  +!(>OjVi%= $ % .7;}Mg % +$ #Wdf59=    )5=V +A   +VWYVXY,/3$) &   +$9+B%0H,8Q2@Z;HaAPgAQiDRjCQi?Me9G_-;S#1I":* + 0 *  ' %-&)0XZ`EIT &'6B^fv="$ %  +.:>039 ,;E^.:Q   89;TSV!   +!)&;5AWLYq]jkyy|_mCPj/Y@Mm*# -!MY\.2: +BLe@Ld) +   #$x~~ZY].-1%$)  $.*5 +-EPdcqrsKZw-8V$B +3 (- +%-)(BDKNR]   +%'-8Tm|: ,:  ,/+/6  -KTmXe|$7  aggQPT"!%)(-  #'5#,:0:L[fysRa-9[9 +#   0) CEMZ^i   $)'2N~/<[ #&8 +"^ij'*2 + +"1T]wt07L   NSSZXZ   &  #1JTezP\|(D80$ +! +   "+58=hlw "(",Ho`l ,H + '" + +6@A"%-  + #4[d}FLa   + +  +>FJ|( +'%9 &%4T|P`{ -#   +  $$(utw7;F   $4@Z!/I % +& #! + &vw|!   !!5]j5?S%   09Z +  +!# + *+6}}-1; ' +BOjt!-G( "# ,-6 (  "1Vd|*3G   + "*V\cTY\!  + /Ta}kv'D +#  "AAJ7;D (  "*6PDPm +, !'  +!#+jjp"*! #/Uc{4?T &  + #GMT4:? ++(3N~KVt(C !% "UV]GIS  +& #=kxes7 "' #BCK #+ !0Say;H^*  + ;AGdik! +  +.DPlGTp) %   ,.6oqvkmu"+ +  ( )LZu+8T' % !  {{$'/ + 2KXpERk )  ,29y~PUW  + +D`nt".H $#*$?AI39@ & #8F`P]{ 9  " +_bf),4 .FSkS^z3  %+3ou{9>A ':Gb_m , +*  !MPXNTZ    !#0Irz.8R   +!" <>E03;#  *@Mecp'?  + !)bhow|}$).!  1P^z4?Z' $"  %'0orylpw'  ! 3N\vKWq )  $  (_af8;B% +  (9F^s'1L !   + TY`^ce!#$;aqy+8N $, +48?/4<! " +!)9Sn{!)B ! #! =@E@CJ'  '3@X2DJ6<> 3B[=K_ +$   BGKmrx"+ + ,DVren '?' +  GHLQT[$-  +"#1HuLWu 0  #  49A*02  !ETlt'8  +! #PUX17A + % $$6Ro9@X +$&!"'Z]e$)2 + (@n|[g4 #  ).7|~$*, +  +  *Q_wIUf&! * -18EJS  & 9[kGQl/(  xx}^af'-5  # !;kyfr6$ "&0tu~(/0   + (Ue}?H\  ! BDMlox!,  #$ !CPlgu(4N ' OPX{~59A + " *Ykr%B %#,ST_(.0  + &Whq{&-A +! %   +''6bdq:=G" +  % (+6Slx9Hd  +./;|~@BH '$J]}z!/N)**AAP"&) +  +[mV^q!5.& '(946Dcen"%1! # #%8JUrIXt.*$ $ '\^gFJM' ! (?Qq)6V# &%'@?O#& +/`q4;N(%( +QQ^01>  +$ "/Khw(D +1$  ! + ;>FOSW +& % '.A_3@` ( $ ""86F"& # +1aq\cu+ + !   24?GHR  % 4\j9Gc /!$ +(*2xxW[_$ % +&!1On=Ji +, + ! +   /.>!%( # 0_n6@R # $/KMXnny$&2  # $).;WZk 1 && &RRZ`dh% " " +#$A]mERq 0   ('8%(,  -Xg~eo/ %& "'$*3git?AK + ! + +)( 3ly$@ ( %  46?nrv%*1   # 6K\{N[{3  !!0+.2     (M[q>L^3#  %>CM_`j" +# +* %JUq9Ea 1' & ""#-wx28@  +  #,;JgXe7 +" )138 +    &IVmp~!-B %% '0`fnuw')5"  , !*4NxVc$?* %SV\;?H  & $/=Y_m9 % $G' + + +# ")3Hnz]i'?!  TW]z}!$-    "8Yey)D # +  +eitbeh ") /_k{'7N +,#  +T]ajms%'1 +  "  3GSkw1CK02;  + +.?Kd#/I"  + Z^i}+/4 +  %MWpJ[v"8! ' " +#-2w:VvYe~&; +*']ciKJR  +6BYm|HUo' " 04?GFN *+#-G0@X( FLP25=$+, $ 8Zh~)3J)+ +CIPZ[`$0FXeM[w +. " )/:rqy('1 +  "0Yc{r&= %  !, %-loslow#(1 &.' /(4M}AOj* ) & $(1x}rqr   'GSkRb .   $,821; +' !)4KDSk ,$ "#$FHQ=BK  -+'3[iSe8%$&  "]aj..1 +  9E^Te 0  ! "*6|GGQ#* + )dp~(7M('')4Z\dglu + +&$+;Iak~.H "*CGPMMP  )5MyXi 5 # &2v}een ,IUlM[t !*& *,5;>I  %%)B\k3Fa ++%+5srw!!(   8P^z]n#: "#!"/qx/19  #2>Tzz'@ *!   !yxbcn*  % . "#" ,mt}WYa!# + $:O[sLXq1 + *  IIR23A + +"# "$1L|m$;   "V[dA?H! # # $6vdu(?  "$)ipy}} ) ) )/:O~$.I "-''1rqzTVa  +#! -P`|0?V ("=CL[Zd#% +&# '^kiz+B + "%&elu9;C!4$';[h~MVt8 (NMW( # ( #3MxGYo) & '.7--8& +& +#DPol}.E  "&#ahqmnu# +.  31>St&.L$" !  + +10=_^g9:F   " ' 2SbSe{ 0 + )nr{DDO( +& #0:Xrm~1H  " ' !]dm/1: + &,0p}U_. ( " +'::Eopz&)5 +  +%'*+9Tsm}': "  SYc`_i +' +%&#@Tcr 2I  " & + +^enUX_ #  % BOe",M,  + %&2opyCFQ   #%6JZw'8L") =CNwx$% +#& 0?Mlw"4K "#% +_fo-08  + + )>boQ\~= >AJfgp#-$" ! +,(5S>Qd - &!,2=x}13?& " +!,5Bax&7N$$% +]dmVYa + +$  !0Z%$ % [^c79B +  $,G* ( #!:x2D['$% V]fMOW +%+ + $;Ea*Ta{fw +1 ! % +9?A`dm"* )#$ :?Mp:M\ %  $ (/2y~3;D  %.DXv1BY# # U\e`bj  +! )&(4L"1K +0$ " " UY\!,,%! *$0PhvJ^p- +& #yBJQ $,-A[u3@Y" "T[d<;D +  + +" #  +MZrOa~*E +# +' +% + 00:ZZa"$-  + '6:Gdg|&3G"   TZ_[bg !1%:[o:E]$  R[dgdm$ %  1=Q|v3E`/ % ' + &TR]57= !�Kx}2E\  =BHnvw%) +  , ,L_r;D]$ + R[d?=G + ) $2R`wUg'B #'  + +,+5PQW" +   5RaH]v,  + +'-4lou29> +' 7J^9C\$   S\ezx%%/"$ )9Mduz8Ga !,"c`jrry,-5 +"! +$(6Uudw&@ !  #MQVGLQ & $4Gz7BZ% " T\eJJV + 04C[cs5+& ==E}|NMV + +#%! +3HYy~,;W # #  49?Y_d + ' &8ex3?X% "$ T^gvv&* +%"4iz4CZ "%  + MNSvu~% *% %5RwDUq &%%(0gjopv{%  ' 0Pcv}.;U $ "$W`iHHS*,  !1AXds'< !% + (+0svz;=G   %):O`ew 3 $ !)HJP(07 +#" +*;L`{*8R #"$ [bk44@$+ "# -VhGVl% & ADHkmu*   * &.)8V{$2N +*!  #02;?GN!  $(8Kv%4N " #% +]dmQS]$ () 2&3Mts 6  !  {46A  ' +/,7Wf8Gc"9 +* " +"+rtzSY`!+ *=sv"2L !#% `fo56?' !  +$ .AOj?Ng +% +:?A]^i#/) , $,8Fcfu",F$- " EDMkqx(.9 + "4\lp!1K +  # +( "dgpden"  * "'@vp&4K +'  v{z@CN  ' $(#ASf7A\ *$  !",uv|x}16A  # 0IXlm}!0I +  ! ( %fip>AI! +!  + +,;IdM^x 0 +$$  LOQghs%# * " %6GhXb}/ QRY7:E$ !" ,;J^l{-F +  % $ilpz{'(3 +  #% "4Wet'2K &" %(,lnq69F + * 0Mox$+D ! ! :;BDHS&  "%*8Lgw*B + "  $norYYb()-& #(5QqL[w) + +#& HJO[^l +$9J]}ENi(  ++5vt|V[f" -Bsds&=   !$'rtt>>H #&( $(>Liz$3N' +# )-2nmn',,  %(7Vsmv' )  !FELimx%  (;hu_m"7   ')*yzxomv" -(('C_sN\{ :' +%;;<;>L + $% &7Ra~ ; +( +  (~{y{#'2#   %8Zg~Yg2    + /./}RP\  %' +2/E`vz4?Z#&#_][þy{$(9+2 %/E78@34:./5+.4+/4,/5*.2'*/&(-(+/+.4038HMQfimz}NUZ$ $-DesPVs2 ! ?>IOUX +# ( )!;NZvP^t 4  %#  (,>**)$$*9Oxu)L&' ``^lkkJLN.14$     +            !#',15;JNThkpsy{!(+ +"  (8F]t|!)F !$ 'uu~uz{!(' +%" (/9T7DZ +  $+% " ) ( ! 1CQjj$F% % jkigccB=?*)+!  +   +!'(%%  + + +    + !!    +   %+.6<@FY]bz}Z__$% 3SawMVu ) +%( !??KFMR#3 "  + +"$?isp}.9Q/ !-+ $! +%& +")$3LgwazC("zzzlgi945    +  "#"" +$      "   ! +!      + #&-BFLgjoDJH +  '2Fao}:$+ $)%VXcotx'+9  +!28C^Ta|!.G$0/. +% '* ;>NiZsA!-  + pms74: ! " +  %' +  % *+ ) +&#   + !&'      & )#%.HKQ,0/!" !4@ULWu / ). # )89Guw7:F  + " * :zl{#1J +$26Gb|@Y 1+$'.\[d+)2 %#   + +6%?".I+6P1;V7B\?LgESmJWmO\qVdxWeyS`uP]rJXlESg?Ma7DX4@U1:O-5H$,@"7 ,$ ! $$  !#  #6;Aegn_ca# !$5NYn.8V 24$ &.CEOLMY&!  "'_km}9E`&-H$>77'A.FS]ah~PP\!!,"   ) ( +9'4O9FbLZxarpy}rbsM^v7G_%4M+A&:"6 .%"$# #))58BuyHML (  $"5ak[h%B+ % ) + +&(3y|llx,-<  ALgduQ]yIVrP^yTau{~9Pj&4O&= 0#$  &-% + +24D)% , +GSlOU` +, & !% &"=GNloxzSb|/=T4 + #"## "BEM&-) +( +  + :t{w&6O +! + +#   %VV]10:$ % + +!5@[cio"(3 + !, ! "&ANVsu@Of%; /0 ,#  + $66=jjoipk).-$' # "7=[Xi4$ +"$ ))0{zKJT(   *4O|v{"*!#)9/ + +) +!OkwxSh,G,%.' ##-?=Fqoufgq)+6  # +8GSow0A^ $*'  E<@387 0ISplmr"%-&"-;Utbt6E_- (' 109jgm[]g#05 (!3@NmWX^! ' +4YfWd!-E# +% !(*)2"TRWafq"0 + + +*+ALf|gt!,C)"GMKfmkmru*17)-# '4Ce89@ - +##'2Kr/N_LQ\mpymnu ++#;P\vy>Mc ' $!#-%$gdilq} &4!0 " &#  +*.`n.:Q !% +    9%",Ont%3#&0efmTT]  +"'/Jv~.9P/ #  *&/qlugmw'.9 +  & % +& !!,FoyVcz(4G &  ( )'' 08Iou& %(1bbgHHR !" +$6?Zu4?V$  " 0+5snxRXa(  #* & $ #3:S}cp+8L2- *# ! 0 )/"4Yatv!3++5nkq<Nt`rv#3G +)&  dcg{z&'4   6`hjx2>T *((AAIou{,09#$1U]usvn-C )) 55U%"5 " "FFMknu36=! + *#*>T]un/E!(! *,4__egeu+  &,Hpyv0/*.  % +)5Mmzo3DZ%  %)&  ,/2oprVXb # )3M|Udz"2   $  /28}?=C   '0+6Kkycw+:N ' $   &79@lotUW_& (5LwBTf/!!. + %@CIvx},.6 %  $=I\n~5CY -" ):;F[^d!" !/Er/AS$ +%-% #TX^nqw')1 $,'9LZo{,=Q , 1 + )KMUbek"(>l}s9J_2  +   $%/RU\qtx-/6   $   )Fkmt (! '2  +  #@Pkvbu#4L )'*  *08W[_|%)/   ++Ve~Tb~!.H / " + ,%HIQWZ` * '+ ) '>BTn}Vj6! ! / ) +$bfj/49  +  &HWp`87 +& #!#-^`gNRZ% ( &""1@VVj,M1 %$)! 78@y{ $;GXqlz3>_ 5'  $ )+3{~)/8 + %! 1L[sMb(H ' ' ##0/6!'#  + 1*;V[i9* ,. + !DIHOR[  + " .CrBRs<  +%! ZY^-16%  % -'AANn7 &,) [`_49A  + " %&IZow5Fe ' +%$ + !"(iilFIP(   ) ,8o2@^" 0/  + %+*uzyknu( #  '8Jm}dt+I $ $ + 79=knt'*3 +  +&( 3M_{k|-J # ! &  +:?>BEN  !&"4FWmP]y$> + & +!!%@AE8 ' + % %qtyGKS!+   $ 9\n>Mh .  $+-fknKQW! + +BUlx,5Q %& %029ils38@  +)=Eb~.?^0'"  39?sw{)/4  "&:j~am!> &  +  VV_CEN  + )/6RWj*M.# &%  (FKRKQS #  $Sf{ANm2" ( % 66B{zOPZ "  &#.H]h?Ru ;% - +$+2ein~%( +!=Nb{5@_ * %+ ""0NNWkmt$!  +$ /1BHQW["* +  +/IWn:D_ - +"- $:T|%-H0(%  &[]b/0;  +" + ""=^iL^r . ! #)kmrLQT ! !!,>eqP[v'-F $ +#$ 244 ,* *kqy]_f  + + *7Orey 2H!$ +)$&/fhpcbj&&/ +  !%6z>Jf' +!3' DIT-08     *FTrfy*= ()  24>rt|yx*,6 +  *ixx".I %,"!-dis`ch!$, +  *""/KduI[q! ('$)+4~),6 +   %crUa}8 +!   5=H>AG +'#. +0>[}3BY3 %BDN|$)6   + +(fv5B\ - & ++joyjmq % + #  3er|7DW +%" &"$.MOYty&-; +  ,j{Yf ) , +% :BKFIN   + )"/H~) "!01BWw(3O ' (+ % 07@BHL +  ! 1+A|Vau$,@ !%$)9?Impx{}6H "#10,2HgUi/@Z 7 &* +    +& 3&AQ`{iz*C# # UW_5>K) +..9Vl_r'7R* +! '#+:JesY2A[?MjTert .F)#!ABKFNZ #  +, , + 5CVq4C] / # .09v3;E  + %)$ +2HXrL[v2  % + %&0ts}pw~2;D  %%4Xgp#<%*  %JJSotz(/6  "" .D\l#0I -*  &%/\ae%*/ + +#%(7JYi6D^!9 $ +   PSV "#  +)!0EtR_{#/G +   dcmJMO# ) +  +*=Vi~r5@X !"#IHR138 !)5(%))Y29Ido~maqN]v=Kb/=T$1H%<3 ' ! $ $ # "  +" # # # %*06)/F,2I:@WNSl_e~mu}ix.  + +$#YT`wvy%&*"+ &! 19Jcxs]qBSo#4M7 -& +       + ! ! ! +  +   + ! " + " + ! "%&&  ! *!:$-FY"4M'>,  +    $ # # " " $% & " +! # $ +" ! "" +$3)B%2I9G_Sc{m|:He+ #' =:Eaej*.3  +#' +%(A=Pl}rK[v6F_,D, #$('$#" ! # # +#!!  ! +# $ & +# "         &*) +' &'$ '#7%4I:K`]mxO]z ( %*/-9UZ_)29   *' +5@Qm~[h:Fb(1K";0$ $& ' ) '"  +    +  !"""! +  # +&)* ) +)" ( +)+)9.=NCSgbrcr, ')"!-ss}X_f" #  #"<;Ifz~`lCLh",G+  &&#!"!     #, 5';+>!-A%1E)5I+7K,8L,8L,8L*6J)5I'3G%0E ,@'; 4- ) +(%  + ! ## +'):@M`hus7 +&&$`blLX]*/ +#* +,6:HexYd(2N 0(( * ) ( ') (" +-&:+5I;EYOXn^h~kwtuz~}~zresZiL[q+9O)7K-@!4 +% !. &"  +!.* ')2GYe{})C "!%"VXbM[]!&   +%'$:?Kg|xR]y3>Y)C +* "% ' ( +%  +!% +)4!)@/9QHQlT]wfor{y{jxWe|FTj3AW$1F 2%! + !! !  /.5JHPgblw)9S, # "HJUDPR/;?$*  ))' 01SjyUc< ')/ . ! +!$?EPlt_dw&+:    +  +)$?GSpFTn #   7;F:9A *!  + #3?To|z8Fa ,F +/ $ "!")* %2/9R_jbl.6F)   " ,4:@LhKXs'   + 37ANJR("- + ,",@IUjfo&0G +! ,!95( "5JUq~H_4 $ " !'%'*D@Vqyal5>W6 +' (4 - $ 0T^zUc2 +  (.6mlr45=' !   '#0G^mo}/;Q , # ! + + +) -& &(BLb|oz7A\ ( , +,8 !+ 1LYvYg6 + + &*2xzrrx67=#/(  '.CHXp`n%2G +)## %(,/ .4,?Xf{{*2O /* +/ +% $ 0(D`r]k8 +  +$(/qs{yy~AAF! !  ' %"!*/?Ut`l *?"+ %  " " **CIVrr|09V* 1+0 , /+ +" + '!"-fgqsux9<@ +!  +((4LS_xVj0J ;& ) + $ $24>Xhqbp ; +!%##/mlvKOR +"  *#9=IcsWj)D '! +" & , " 1@@!$$#+(@@Niqdv(E$ # / $ +*3 .5Ba{Tb1 # $ !//[`z~7Fe & )  +HGTbcf57< &"!  ! % ' #)'A?Lfp|KWr5!',+** &"=\ix+9V $ !! VWbTX[*.1#"  ",09M_jQ^x,C  ") +*'5OYil{)E !! + $gjtfjk6;= "  +% # '0BVbwzKXr"-F' +* (  "$3JeuWe!<  + )sw?EG !%0$1)'!%=ZfJUn 2 + + ,%4Kdq;Ie /  &#)3msu;@C '   %'  ##:;E^hq]j)@ #/1'$9jw&3N(  ++-3E^qwq}%/E %-&% +Ckw}3 + % +&0NT]NPZ'*5 % # +$7;R_e|r}3 & , + + (MYn>EY! + +:@F__d669 # +  +-/ ! 24@]hx}~oet^mWgRb~JZv>Mj>Ok?Nk>Ok?PlBToJZvO^zZigtlyr~Xfz1 !) !) -?K`ip/4I!  OVZVYY%&)"% '* ( )1'D8Igfwr|`kOYuBNj6A\'4O!,G'B">94 0 1 1 0 . 047(D*4P*4O,7R4@YDQj[io}|[h|+9L+ +# ! +1DOcLRj &: +# ipsikjCHH&), +"(## +3$1NHWtw}lxWb|Le -G9 . +# +#$#! !# +& +& (///- + ( ( ' % $ &' " " ! +& ( &,* 5_f{ku!&< + !ELO~IOT#(1!   ! %$" +&8)9S?MfDSm;Jd&4M 1! &, ' + & + & & +$ +$ ')+ & + % +$ +$ +$ $ #!" " $ ) * )'% $-- + '25MqsHOk4  &)/ios`eo8XPXniqr}ZfxJXjR`u|=Ig1 # + "klphiv:;J.  $- - $ ( 2%A6B^\gp ,H & ! + 58BEHBN +'% +."+ABLe!-E +! ! +" $hlmQMW&#/    " ! !04@V^kZh4  !  +>ADqnuC>I" &# ''ADOhr|-:T# +lprgfl-+5+ &"$?MWsWc1  + & %)+uv|0/7  +#' + # ,)0MT^zs1;U# + # + %X]]x{9:B  ,*$+1Oen=Gc3  +$  =CF|z13: !  # ( 58Wag8 +!  + $mrs>=A +  #437TEPl $ !&$BGJ:6<" + $ + *.Knvlv6! (- +$(0hlnUPV'%,  .' ",4Nku{9C` $ $-% RT\`]e&#+%$-  ++!(?dqITq"= , &  ,-7|64<   + +%sx}pov"!+* !6KXsWi~%5 &  +""cklEGN    ) $:C^o': !(  AJIjir"$- +  /#,CwWyt$2I! CKHEHN +++5Xc?Qj % " " t{v^ah!%,  /)5?YP]z%="*! KPO9  " * " =EG&).    #$0L+G +$ +( &  $,2y`bf") +    2S^yGXu ' ' #& #-TZa9;?% + ''3K~P^~< +/+ ! +HO\mmq" 0?Kc_n&3N - )  .5A~BBI')'/Idor$1M) +" !!  %0gnv.-7 "(=Eay5@\2 ! ) +"&1X^frsz * $ )S^{@Jg+ +! ) ! !ELVKMS + $7lxLXx"> +# % +#/5?,/2    +# + +7PJVt: &- + + +15@rw~  +(GUpjw%@+   %'/pr{jnn   -aru+7R +$ +!& " +[[aQUV + $=zv2=Y '*,  + ! $WVX<@A "#5N| ! $ ,Vg);U' . +* ) $  QJT.5=!  +.[lxAH  $ +% +DRiUby(4I!4( +$ !   (SS[ILS +  $-@NbN\r&1G +'!  " ",35;QRVSVZ   +# 2?K`nR|Te$2K2 +( + &"98@rpvY[_#  !(3FsL[w%> +   + "">>Dzw~him!% %9hur@Ql(B) ! "!+POUwx{ #'   ([g{R`{*4M1%# %**  +&VU^*)-   EQfUb| 2)&,;(*8QPZ::>   -8Ko~,8Q1 ! (1 %  57Ars}QSS  # $7quO^u(5L# +! $"  *),7BDN{|lnn" " +dpt@I`*@5#2JHXql{/?R +   " +# $$'4LNY%&* + # !KWngo#+> # +(( $.)7QYjMYo&: + +* "  *,9lmx549   /;R@I\#+;1#7( &@N`{s:EZ-  ((  !"-:;Eqr|LLR!  !8dtRb/;S#3* !   '1 /+ 5'8SVhsITk'/D$  !#&% +-,4`^gllq"$,  +   0GTqv:Kh$>&   %# . - #+0JEVql~u`m4@W!6 '! !/$$!*EBIusy57> +   " #+8Rhx[k$6Q1)$"#%& ' *) #$&/0KSdXj&4N*1-   +0-6[Y_OSX!' $Oj+C.'$%  !/-6`^g@DI& 4]no6Da#> & ' /* #)(#67>hlrlp|,2? ! " %)" +-64":4@Y^n{Pb6Hb*H"  "  .'2Mbm:C\%<  ') !+HJV}|MR["+ +  $ ! /):"0C-W)>- !  %''! +&=?J]_ifgp>=H%#,  !  +  #$""&.45:)@$2G+8N.=R2@T5DV7FX7DY7DY7DY6CY5CX2@U/B&+0% +   +      " $ # # % $ % $ $ $ # " +" !  +    +&.6;FLRZaeUWd!#3 4: ,4GPneqMZo,D<@D=@F@CHCFLDGLKNTX[`dgkpsyz}215"-)   5A[dq|Raw4AV(< )  $& %&#   #'58@Y\c<=F    $ ' $# '5 .E=Kderp[lETn0@W$2I-A%700.%     #*,6QS]VYd#. + /2*8OGUneswj{Tf8Jd!3K#: .$   !    # /23AHJWegsPR]%(3#-" ,,)% + %'6MXf~|~k|XiFWr7Hc/?Z"3L$; / "  +   +"  $ )+7LOYxyINU% %  +$8*7L=J^Ucxgvt~xnbtYjTcM]y@Ql8Hb,;S.F"9 1)$ + ! '* %     +#+-4Y[dnpyQU[(.3 + ( +$ +##4%2B/;O6DW>L^DQdIWlN]sRawVf~YhVgOazH[sCUo=Mf9Hb4D^.=W%5O-G&> 94.' " +    !$ !# $# +   "(-238;CFJ]_b{}LQT %*       !( $ #  ! %*-./0!1!4!5 42 . +12/ -*(&%%%"!!#$ " #   &++057=?MQTgiky~AEI+05!( + + + +%% +       +     + + +       +  + " )%-37=CCGK[`buyzlqtCGL%*/" +   +       + +   +       '&.55=AJPUeilx}Y]b>CH$+0 +          + +         $+/3:6:BDIOX^cmsyafiFKN7BJIMSZ]fnsyty}^cfLRTAFI;@C5:>28;(.2#(-$*.$*-%+/&,0)/3,15+3607<1:?4=A8BF?HMJQWV^c`gmkqv} \ No newline at end of file diff --git a/share/qtcreator/examples/15-Utils/prior_data_320.bin b/share/qtcreator/examples/15-Utils/prior_data_320.bin new file mode 100644 index 0000000000000000000000000000000000000000..4d8aab972a776022267be3ee847867c96eefefe1 GIT binary patch literal 67200 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 literal 0 HcmV?d00001 diff --git a/share/qtcreator/examples/15-Utils/shear.bin b/share/qtcreator/examples/15-Utils/shear.bin new file mode 100644 index 00000000000..a739569dc53 --- /dev/null +++ b/share/qtcreator/examples/15-Utils/shear.bin @@ -0,0 +1,866 @@ +~yyxytuprylmwhjrffqcenbdo`doaepbfqfhsikulnxnoyvw}|ru}_`jNPZACM>@K68C/1<(*5!#.(#  +   +  +  +    "$%#%-0/787?A@HMMSb_hrrx|gjnUX\LPUAFK9>F47?(-5!)!    +  +   +        +  + +     #&%$.)*2//787?BAIHHNWV\jgmgkkW\]MRUADH27;&,2#)!  + +      + ! ! ! # #$%'()( ! " +" # $%&&&%"  #'  +  +  ! "*.-5:9AECHMKP_]a{w}mpuZ]aBGK/47!'*    +   ! +$ % %$ % ' ( +' +' ( ' %#    +  + !#$ +% +% +$ +% % $ +# +# % %$ !!(%,54;DCEQRQijkvyZ]dCFM8(*2"       + " & '#   +   + $##!'(*(%!!#&'+-047DKLjpsxz~aci>@H'+3&  +      !$&% $ """    + + + +  $' +.26": '?$-F&/H)2K.8P2Jb%1F$8 )    +  $"  " ! + ! (%&##(9R\j~~pO]q-:N%8#   + !&(%"  #')DHHsxxns{,4;   + +   +" &+=;JaYh~hxIXp'6J/%" ) ' !$  $)/47MQTquvFNU)0(!  + ))=>I_]jh|M^uGZvvIXt.Nh]en "( #.#:Hctz(/9   '- "*+E08@' 8".IwIPU!0 #6 <^iaij (/*+ .GSq # (,*,/7SHMP $ ) )!-Ls]ba!  $;Zi179 + $!# #?NkOPS"(, +*$ /H~-/4"  + + *ZisjrQTV"(  + ) -0(%E20O><[KOlZelyDCH   !9Uc~Si +4+:4( +* , '&!  '#;0WLUpoyPSWSRTFEI # "" 7Tc~e}'G6 +&$""!" $ ' $  &** +) ' )0(+D7=YMTsdm8=C'&)`__cch&$) # '7C\}Rh,?_)I @ 5 +1 -#"&$ +# (,,' +"  %:5EQ /01[[Zxv{ ! + !1Op\o}:CR  +-/OQQHGP#  +"7Xe~|q`oR`q>K[*6E&3'    $'!" * 8!0P>Mn`pn}&2E   $VXXvu~""+%&!>I`rYew# !!'" $)UX]a`i&' +# -Vd~rMZu+8R&< 4'(-)'  - ""@EKkq{GZu#: #!  (!%,dglIHS  & '?swBI^"';  + $*#  +1?PXzJYt&@ + +  & */3Je8 # )-+ +& &,8Ljyu+H  $'*('TSWsx#-  + 0XkXb{(? + +,+# +-;MRbxcq#A %2"&5"#)tsu¿TZb !-Fw~8@Y7  ! +% '$ *&CL #&1@XS[s#< $ +*1"$%(AH[uYg:* !#3) /,105>%  /GUobi3;R ) ) +)  # "*DL^|Ra9 *&$.B?Gsw&*4 !   8anz1G   $ & #2>Y8H_ * ! #%( ,&4Jly9 (/ ! #$6;>37? " "%)?Lg{.I& # /&  ( ,ARiFSs; 2 . " PUY(,4 +$ +# "3S_zj},G**) $ %)CYo4Cd3 1 ' )ejo}#+ % # ";fshz0G (  &.Asl}!1P2, + +04=qs{(# +$ ,CuTf4' +& !#( $ $$&$O_t\s"=% (" !^`dJLU  !#?K`R^p  %(# $3IxFVt0 $$ &$%/FHP!    ">Nb~$2B %  .5Sc{2;X5( + ".$>AKBDL    %CQe\j|0 + $*(1>Xqmx)E'$ % !'*6oq{=?G ! &GUi+:N +* 0 "3ETnBLg  +# # # 9@H ! &FThEVn4 ** .GRm+6R 0 + ILSCEN    $APdt,MaFTn)' $& % +"Ye,7S ' +'( Z_hOQZ $ +" 7FZdt - , +, AJeo|#= 5 +*+1;Y[c  +!-jzez % '$ #P]sevK\y%B!.J2;WHPl]hx>Kf $ )( +)\eo#'/ " # "6\m|0+. ;H]s^lCPl/7* $ & +* . +* ( $ % $''*'(&(&' #  + */.AZf}kx&="0   + -7@?BJ  % +( )9RLb| "9!  2]lGTs(5R&B 2 (  $ * ( " +  $ + " "'./ ) " :3Fcn.:T * & * ! v|SVY   *  /F|o'A "".FXrt}4=W)' + ! #    + !.-.0330 / %)/ + ()' +#(/>XfvR^y4 %$ +DKRkmm$%& +' %;ap(D +.* #54F`JQg +%(%( # +''!  $!3%0C/9LEQeIUjR^s[h}_m\h~P^tGUm4A]"/M= +2'"165 +"$*#5_hx~&2K%! + ! "(10// .Sa{ /K'3 ++(5/=W~EMc"4 "%    # (!();2>> + ";Ha)7P $ +(  +.,9Qv2GRRR !   !.G{8C]$    "#6KVm]k^ngzoz>Ib/ %  ! ""%!5*9MESknzAJk > !$#  +FO`ALe' !  '1pvmmm"# $ 1_lIRl ( )' +  0":&C'E'H 2R.DaM`zr;F]4$ ,,  !/E]kZd)1M- +!! 1MVhlv0! +%   KQZ036 +  # +%GRnLTl +% !"% $   '25%='5J>H]\ey@L_$(' * &!5>I`p~r{=C[( + " +$,>_k)6L +)#  + )1;LOQ + + -8R|ELd   ,( $ #+6 2* +  $$*;16K]fITf)/ '8& +)MZpFL`. ) +"1;OqP^w 5  +' %&rxloq +   8Ze@F\ "! +!  +0 * ! +   # #"9?Ifaqu~(/@ ! +"     *>UawEJZ#!! &!-,:P~o~(>2 ) IQ^"&+  +.9C\Jf .N +:-(' '6 3 +40$/-=!2 $$,,- GVi%+A " (%% !&+Awk|+F0! NWd9<@ ' "!9x.8R$!%27IgzL[|5@]$,H3 $ # %/ 7+"+) " # '  &9udm / +%(' + '6DZ4Fc! " -$ 0;Icch "( 'MUp%1K %(1=FZgsOWt2:V7 /: 6 %%' ! ! + ++Zh~6Aa%* +,%#)cqLa|-'$"$4<=B + +% ! + &.Hkwj{+E! ( +1JWoWa~&0O. ) +%+ /!( ( +  **9N&2Q  %, " 5ASex 8)#' + +%]drjjo  !  .?KgRe!=' "( !-B`oDQr!@% & +/$ '2 #7Saxfr%C +&( !  0P]p}0K.& ," >FS+,3  $ "%Bbp?Qp3(%$(4Lq]o0@\/' & " +( %*9PGTt * % * + +6H/C`6  , ' (0=WX^"& & 01<]7Ea+((&"0J3B[ ) # % +-Wgt$B #(" 1R_tZh4 $ +",ejp<=I) +( +/4N[}&4M! &,* +&%9SU`y/#  (&3JzBUt* "(""#"/E|}#7  !!RUYopz''7 ) -!!Aumx3&.( &9LgT`y0   /MZq)C +! +   ,K[t-6KDGJ=>M#' +$&&GRtKWo  , +.$.Vh@Nf/ "   5sCPk&' & &!0J{COc(  ,/3VWf( ! #"& +3%F?Jl0=U  1+)Bvw,E +), ! "%.D$/F "1 ) /XgYe{$4  $OP_. " )*18"8U`hs+A ) , 9F_Vk 2 , # 'CKcXc{ *- $  $-:X|ly".? + nqtUW`@BO$(7* #/ / 1 - '#-Jr}?J_. /$ #`nCXu +.&" !8gp&/F#  ' ) 2P_~}+9M "   [^cxy~_`h;>G$  # +'' +." +& )-2=Yjw':   2  -C+?]+ ( +%-4L\d~ *+ * #!.:Y8G\  &  ILSv{}MRU$'-& 0%- &4+ $4EMjIVn$ 1  &ANd|$B & + -'  '#(C $  '!3- .4 0 ! +"& # '8T[xCQk*  )"$6DYK^y)&"  !4do$,F $ +#  %$-Hzau 6,!#!)}pmrQQW-07  " ++ +.4+D6E_ZlctTb|(B* 1 *7`h|$>!%&!%7Zg}8Id +#)$ +$.C~DOh& %&%.R[uy1H+" &!gmu~KHR!(  "$! $*&(5/IW "' +% 1;Phs(B%'.  #09Q-AY("' R[crrx=;C$"   % &# +.$1LO]x|:F] + -0 # %ZVb7D[ $& ) $ +- *EStx$0I)-$ +:K`o~"0D! "%OXlVd} /"$ GPgF\w &$)  7?Icmr8?G( +  +""  $.>5H[Qbyyw-8P. $ ( 1-!'HGVvx5C^ 2' $(,Cn\k 3 )cm})7N( $#&.BvWm*'* )1;ovz9BI$ +"",( +% *$3GSfz%0K + %  &+ *- 7:Jh|?Ok) % $ #* 3@TlQ_t!  !-s}BPg%:#!#)Zc}ax1,)  )3t{pqy9:B$   #+0 + ''4L\l*3R ( + % +$ /!(EktPa = % )6 + "2C_GRf + +*;hx/H % '.Q   !"-9NO^{ 0 !5'.M`}*E-& KRZMOW+,5& + % +($9BNg|AJf ; + $ $"2 ( +29Ddv`r-@^1 %) # +-8Jd49M + +"  3?Sq~"/J " "/ & '.?Z 4P/$ +! AHPY\a.18& +  + "7;I_ixOYt!; "%" +!" +& ()IR]{eq!.M, +#+ ")2DZw07L %  7CYAJf . +"%&*)@x*?[/  +! ;BJKNT'  + #" *'7MQaxUb|*@    # /5"%%?AKev`g+1P! . +/ $,BRp+2G % + !AMeY`}1 # * % /[h4Hd0! +! :AIRUY36 '. ,/%#":L_|{%,@ $  +'NZqu|!> (,$;G_@Ro 1"  ;>Fvz~  !,Tby?C`3 ( ( %2ItI[x4#  8V`ni{4D](>& # % +# + + +"#,Dxn{#:( " .Xhuz3 ,) -Xf~N^z7 % +08_bb(,5   ) " $+9NhvN\r,@' !#)( "  $ 0,C7F`^nPa*:X'%#  !)* '28Slz#9( $/Yi@Ff ,$!*3A[R`| 9  +$ */7quyHf*5R%2N4C_pUc#<  $ (-5bfm'-4 $,  % 0%6MgxWd~%/G& /6303&  +-!-EP\t|\k-;X8 (,3 /"'3&%@Q[wjx!9( #0[k{Yd$= + $  +')2zIPY $/ )$ -% -!3HGYs_i*4Q +1$ #' ' &  .!+ABOjXfq~Zh:Hd&B 4- $ !,' **:Tfxjx!9)"0\k[f$> + $  &(1fju*0;   +" &*9;Lfk}tLYx%2O 1 (+  +%(( #  3(5SLXvkv~nK\w/>Z)E 1## +%! +& ++'#*2GL`yiy":*"/\k\f#= " + &(1RT^%(4   %! "$=?Rl}jy>Kj%A (1 *   $!     % 0%C3A^FUun|pRh4Hc+E+! !)1/ % & , ")'>Tjjy#;*"-Zk[e"; +" + ')2ghr46A + +#!  0,=YexwOYw*D/ "  +   + "#" +$ $ $) 4#@#3O7GdM^z`qs|f}ZoATm1D[-D 4& +! #' + + $! %"3JKbxky$;,!-YjZd:! + &(1[\g$%1 + !  1$3LEWv{gsP]x13:IBIYMUg\gfvp~}ypZiBRk9Ib*;T#8 $ $) 5, ! ++07MKXlvly&> %"-XhZf 8 +$" +.7=?I#  +  + % )%( 6,AYWmQ`.=[!=*00+)*,&     *!7.E+:Q3BY8H_@OgETkRbz`pbrgwl|qssso~jxcq^lXe~OZtFOk:C_,5O(0K )B0$ * +' +$" + $%  +0+3GFSeo|n{(A +# $ ,Ue|Yf!7 %# +-09ou|28?  %%) ( " !!9;OhxPc,G*" + !& ( " +      + "# " # &)+.1 4"6#7#7$7%6 2.,*( ( $    + &$  )25KY`vq~ *B& $ )P`xVb~ 6 $ ! +-/8TZa%  ! " $ /"1IPb|p\kN\y3@\%A +    +"'$ +!"  + + + #+" !$  +   + &"#78;Q]azu!+C'" +'L\tO[w4 #   /1:GMT&     +  4;Ibizt}iyM]y4E^ .F5 * +$         $ ) ' ( & &## ! + # % $ $ &-(% ! #  +")'/  +)',<9lqz.3<    #- )!7ERkWc-6U$,I6A^nzlyMZr;F^/6L!6( ! + +     +# $ $ +# # # " """ ! "$% "    !    $ )2>HT`hw{'/G &!'?Og?Kf 0  # :MiOYq# % % "5o 2 +! ) $/or{|}68D %*1 +)/&>gsju!,H%, 0KYk>Tr 7 &0 +''D`pXbz) # + *$ 1fxw +. + ! ',7z}bcm&&2 ! "( ) 3@Idlw5B\&% *!&%3E)>Z0)1 ' '6Qbl0! +-& 0]ohv - +  06@[Zd)  "0!:2 2:WFUo* + " 1j{3K,*, # $:C_pz!(< - # +0Oa}R_{- +! +( Ok "(% ) +/[fP]x&*( ! )Alv@Ne + +* %),9Rm~ 1%& $#kq{V\c'+     +#"9FTpaq.-% +)' %:EeBOk (, + %/HyHZs $)"&$/H}^q%%" (~W[c! +  %-!&;R_x+H ) # +!' %"Ags6C_, ( +, +" +"2mxK^v#)  "+5EIP& #% /A`lAMi* "  # &-:Eez'4P. # - & $@Jcgz 3 ! !#$0[e6Ia + ++  + 8?IMPV #+   " ".=Op~u!= !$ +) $ )#Ahup*E. * % %MWnu"; + $ +*$ $JSqy):P + ++ + + !JQZ-!& #'V`w,G $%.$C 1CPcep9 #2" *. 8fugx:- & +# +-]g);V,% *$/7QQd}%9  (w}xvz439!!%%""5ESh?Id ) .-%+?Kfdu8/-1ak6Fa 3 !## (/Ht>Ng0  + "  %-sos338    &7Vczmx$A (,% (%?Se`q 50 .4gqFXt5 +"  %#)@_j+;S '   " 04:egi+*/!"  &7Xf{KWt#! +0)+ +$+E}[l0-)(5oycw5 +) +$1CLfu)?  +  NQUdgg.25 +$)( ();^mw9- ' '' #*5E[\m0 ( &'! 8oyx-F ! &   +9AY[n 6    $(psvX\_#',  #&"(3@VvERn0 '+((hy]n0 +& %) %":mw.?X "%( ,3K6Ha *! -15SY[!%! , +&.Pi# "/' &;s*@$  " =@CU]b & +%  ! !6C\`m!-I +! -%- +-9Lxct 6 +& +$ +,)!9dnPa} )/( *[hkz /#   X[^NX[(27! (8E\Q^w % ,  %EPehy:$!*(5`jgz&< ' " !GSlIZp'# %(+|~~PUW!%  + ") +& ( &0Zd|6BX  "1?U{%5K$  +FHLMOR    %+/7E[gu -D'$ +!,30_io$@) + ( # -T`wKWp + + +# )Adr`q +/ dfgRT^!  !  "  7R_yJ^v1 0 +& $-Ioxx#/J&" #)MZueo' * +( +JTpCTe SWb+ & (  !%>NZu)=V.(+! +!1,'Dv~}*7O ! #&FSnx"9$- & ';C_|+;J 000QU]+# % 5T`{n8Og " $6#07Tw}1>V # #?>fjj'-2 $ 9P]xOYn ()* - & *+:RfyQ_x + %' +"-Gfs5?W ( "% ,"3nzDNi1  !  + cbbz~~*/0  &"  7GVqLVj! & %'- '-F_nbp)!#$ +$=VaMYt0 $' # (CPl'C $ )# +679|.25  +' +/;Me_k 4 & +# $- % + + %%>Q^xo~ 2#" 5HTpr#,H " . &*%*FsXb+ & ! YY\:>C  +  # +"5=Oew5 ' '(  +#- & !%$ 2COi$;& "-@I*/< +-2( %/Ibv:?\ +- &/ )" ++"2Eevp,E[ 4 $ ! "& ) ) '+19Rwdx'<!' ! "1;Fc~|*8O ) -&'qtz?GS "/*$&BYlEHh + ,. ++ /$;iz2E]6( + '+ &*'0HQ\u->T .& !  &!-IXh,$  "8=CIO\% + "( 1M\}{AKl>- ( ( * # -CTcz{M\t#: + !  +% $(1mVe"0J /& !%  +,?PizHPf'/F / ' +,*Ox4C\ &!*&CM^~'4Q # , + 8>Bsx&$)" 4Oax^l(A1#  '# !$(8N{s2=X 0:#C&HGZ~Wd , +& +# 01'2S@Mk 2 . " +! + "&.otxAEN+*/=Mcx+9Q +,1  .* ';PtJ[y3DcK\}u(/H +%  ,%;tht8 +%1 &( PT[npx"&0 ( * + (8Lo}y.;R& ' +&1BjMSm2 +#3IRsz+8S +$$% 46?68A # & 2P^w};F^ ! # ! ! +!-7Dwio"&> % *% -#Cy?Jf +- ( !  &(2mowrsx!*  " $'%2L~@Md (+( #  '/:v=A[ ' ( +' + + *LYxCOk1 $* %  "TU^=>E$ +   "#=IXu9H_ "'' + +$,:ip~im4! +& + + (+Ij}Xd6) #  +BBMsrw()1  $! ,DW[Z +  *";co_fx"%4 + + !"' ++CMmh|">+ " +-:" &) "<@F8=<  "(9E_[dw'.>  #( &4:V0?\ +*%  + + '>E_COm(F6!! % >?Hvww#''   +# (\gLYo"5 + $ .6;R~r:E` +(*$$;O]uP`z9  &"<=HXYY  +$0{BQh. #!$! "/5Ir~": ) &( # /Qax*:R ' $1$MLX??B  '".FXg% +    *2EyWc|/ ( % % "  1Qcy=L`* " +$ +0 IHS--0  +   .BNhLZx9$/& + #!*;?Kb&;,.# ( +*Sezu!6!) $ "#%WR`ggj $  + +%4Xe;Kh!= '(? +% " #(7kv?Md3"  %2N^yep%0I%! +"$ %PKVFGJ +  ' +(!-Dy?No +3 ( +,."  # (.=Xaq3DW #-$ 39HfHTn5 )* + + "#"*hdm/04  +'4AZKYy& 3 +& + ) $" 'OYkk"5I & +' +& +() +'@Lk|AId , %*  + &ifl%%,  /IUqSc$C,7 , '% (4:F\}f|6I^ , + * +&-0:%1Qitq|'0J +!)/ !0/5wvy¿ ! :boQb&C ' +.52 2 , $%1Mq'9O&% +, ' '"-L^iT\z": & &&# +   !%IKNsqt$ $%,Ht?So&B+ +-4 + )/ *3 4"0M]nbx1?V3 + / ,- * 3EPqAJg )'2"   KMQdbg $'09WIZv 9 +& " .1 +'3#%Cix{DPh2 %' (&1*<4?ahwan/' " +* (/6 5"DFTuzN\|#/M +' '/7.*89Buu|NKP +  + +-AJjBOr$F*%,& +# + % +&/IQr[c|'/F ((47-! :6Dd_p^q+=\<,  +&% +   %DBO~}HDM  + .DNm8Df6. &% + " +# +*/5U|_j3/' .-#)$# 66Ebm~z0B_#@4 ( +( &,NN[45> + % %Q_{:Hd 5 )* +  ( ! +'-'2Pq}>Jb +.2 .($ ! /!;,GAPjduI[w!6L.($-- #%3hht-.8  + %'VdAOj 5&* $$  ++ ,8Xh^l(4L3  )1&  +  %7$3MSftarS$ +&0" (0*  %+FJ]y}w=Lh 6 +.! +!'  "*7Y_k( +   $.bp~9Hc %# +( % #" +!4(1@Vt(3J" "++ $ + +  *. 2(@3D^^mp5B] +/ +# .&<& % +(9CM}{}% +! $ +/fs8F` - % ) ++ +- '1?Rk{EQg  (+ "%%5 # , +A@Lc]k}o~JWr)A'%,+ +'  #' -5@eoy|~( +  $ .fslz:E[T_yn{bu@Qp$4O6 )& +% % ! + !+19ciq)*3  + $-aoiw/=U )$ ! !(+*:P\t/ # 25=^`inqxQSZ+.1 + + "   +%3!+@4?UHTl`nulSg/B^#>* +! &$"  .18^ah)*3 + + $(an`n+8P -  +!$  #  " (8m~5AY0)  -.5RPN630" +   )#<$3P6FcN]|bswv_rI^|5Jg 81( $ ! !" # #  $+*.?=@MLO*+4 +  & &\iYi'?&" %(% #     $BTe'>+  89?b]Y?<7$! !    %+, /7 *F0?[@PkO^{\jdtpzvi{bsYjK\x8Ie);V/K#? 3 +.# +   "%# 969a_`24=   +) %O]yN]w 9% ( '  +$$  ") + ):Nwz 8 +% +  !\\_¾|ytTPN1.-   "$!  "$ ( & +)/4!;!(D%-I)2N-7S/;V2AZ9F`Id +' ' AAEzzYZ^69?#&."     +! $'+* ' ) * +( '&$  +   +# $! $ % $ +$ $'&   &8Z9C^ ) ##+ #  $"! +&! + 1bt'1I ! + UVZmowJLT14<*  +  !!   +   +#&(*&      "!! +     +  "(.6;BNTZpszden#   !&3OwPXs5 ! (&  #  , %5Ebgr 9  +  lnrggqJJV>?J./9#%0)!  +  !  +  +        !+**535?UZ^qvxvw*  + # (Cfwt~%-G $.*+&(*4 !+"# & ! " 0NrQYt- ! !$)rr}[[fJJV@AL24@#$3+        &)+4?@IRT]hhr"%0  # ! ;Wg^j,6O5 *!&  "/?AK8:E& $ # 8Sc>D_% # + 037xylmvefoaak^aj]_i]`g_bfaafachfglnqu{|/2=  &.3Da^j/I' %   "BRo?Gd )    &).nt{!) !  7CUqy.;T)%) %  +(1;y{^`k& . +% (Aw(1L# # &ACH18? + +! M_n1mtv#'   +&  ,ViLXu ,F% +%#""#KOW| $0!/% ,Ces&1L'' AEN4;=  + $%4DYBLk9 ) "  &  38>aekBHS  +% % +"ESjmy +. ! +. \_eV]_  !%&:`qx9B^5 !( +*-3nqu_dn!'3   +(%*AuOZv ## $ +,7{~z!%  &#9I\[k)5O - +$)(  137"+&& # 1IZsx9D]& + "  GIS*04 +  + ():l}Wh"9(0(  ACDX^e   +",& /Haq'?% &  dgpMRW  ,*HXmv0?W"7 ! ' "%*[]_pwz '"  -/":HYtDSm *  +!'-3 % '%2Fxdr&.F ( *# #/15gjj=EI * $! *8Kc)9R )#&,5HLR + +  +$ '(>Kces6 $ %,"EGLlsw#*0  $ # 4fzar(?  *INWwy*-7 + # +( ""9q5A` 736 %  !?CGCJP#     &EVk>Oj5$  + '2y{Y\g& + &+#LZpbt=Ii - '0 +  (./7VX^fko%+  ! 0C.I(# +$ + +.4@'+7  ,"'E$   "&CSin~.#&#/HNW[\f  + &6$9s~.;U. % $-@8FyvzUYa & #% !-:SBMh"$ 07@w}24>! + !4?MdLWr&0I2 ,"  MER38C !!  !!8Zi"> +$(GMTcen#    (( 0We~m{9F`6 "#" " +"  !83@piuTW`(   ( $2BZeq +!((&djq68A %. ' + , .GfvESk&< / * "  %%2HGRU'' +(.4>JQYbfl" &&)'+-7$ 4>MkUaz$1G *  $ +$#.!!.4<`fn*.6   $ / !Ni/9V 0 % ! " '(6yzdgp*! + / 05?Mi~cp9H^(='   #) %  + #:?Epuz02; +'" (Co~!<% % +!";;IX[c%'2   )5* *!+F]h|Vc{8F]&< $  +!& ! + "6NkR^y - &'*]^l[\d"   ! +) .!:=H`{kwHUk$0G2 (        "(0NU\.18   * $:ix,5O&'& 23ARV\!+  $0( +3=Rox\h@Mf%<(  +$* +  #+=ELz]`f$ ' & 65Eeep 0 & &![[i^bi (0'* +" +("5 4,6J[h~frFQk)4M8* +'&#  $-BHOty+.5   . +""0Mgw@Je ' # ++nu{*2< "+ ' ' '>09QKTlbl{t]iEPk*2L 71- * #",,% !8@Gtz`dh   ' &@Olw)2L #* # >?M1:C%   %   ! +!71;XQ[zhvrr|vjy]kO]|BOl4A^+6Q7)# % "   + +6IGKV`dotutvux~ &!% +/JZugx .E + $GHRz{ijtcep`alYYeQT^LNZKMYLOZMQ\PU^[ajkryzGKR +* !!:fv>Oi) * % kjtux|"%,   %%4D^i{ /H+ .08GIN   !"9dt8Kf3"% &HHN+-1%(8Q#=   +#$%'/wz| & -FXsL]x/ +! & "CFLOST  +! +# +*Ch{{+E(' $ !,06y|+/1'!  ->XVe~  $*% TX]xz{ ( .K^wt+9R# '&"%/VYY    /FnDVp 3&"  ORX69:   +;Ja&6Q(1   )}pps!$%"  $P_wNc"; $ ,   EJSXW`& + #!6iwq"2K * ! +  !.x}CBO + # +" '2;VS[v +($ +  &DIS31B + # $1FOkw},0K ' %  .4>nu~rp~,  (9fnIOl ' %) MS]QR_   *!!'Au)0J ! &%/u{==J $)!,3M:B]3$ +  IOZ//< ( % '?Gbjw2 +-  &1|~&&4 +  + 0Yc}1=W%%, %JPYlkw#$1  ,:lu]j(%  !",1:su\\h(  (&-I.9S & # 'Z]fRS^$ + +'.8WO^x3  &"69AGHS   (";Ff"0F # (% #fhp<>H   ( *HStLXs2#,$  +(.545@  &/P\}l}#; .# #  &.din*-8  +  & 4Vb*9R +!'  ENR $. +   & 8]kXi 2 #% *2v& " +'AVp2 & 59=&(2    ) 6UdOd*B"& +$ &jlo+.6  (/K\{y"4J #/ LOT.1:    ',GWs9Lc +, ) +" -3:69@  + " )@LhN_| / +( !.$gjoAEL  +! +%7A\k}#2K . '#;@EV[`   (3Iy7Jf ! !.   ;@F|~puw ! %8\lVg!7 #"+ lpt"% ! -ESgs&5K   +!!89=39<  %1>Pr+:N#  "  37:RXZ   +;o0BV  "# "prvhno $  )O`sSdz3 + !# _bg488     !-:Nev&4G %$"  69>C + +  + !7Hb|P^q &  "%  +.39tw{jko%#"  09IdM\r0 %  %.4Icy|=Lh2 " ( & & XbjU\f *  +#,#0[gl~(7Q'   ! +!$KRZ_ek&+2 "  +   # -#0JWfrzK[v .E) ( )& $%/"&cfmtx}FJO ) $$  + !#( :)7SK[xn^p-AGilpLOS!#,! $- $ +4$4PFWwkp8J_$6"  +  ( ! *CCJhho-,5!$.+ + '# % $$-"?':WYkOd0L.  +" $ + "! +#VTYVU\""+!  +   %1 :.I,/0:()3"#-'%%& #!#+&)/)+313:?AGLMT`ahnov{xtr{spztq{us{srwxy{~ \ No newline at end of file diff --git a/share/qtcreator/examples/15-Utils/wozai.wav b/share/qtcreator/examples/15-Utils/wozai.wav new file mode 100644 index 0000000000000000000000000000000000000000..bef54be0109ae4449c8740093e9450298d69c84b GIT binary patch literal 17678 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 NPXqtc!2g#9{tt5quC4$8 literal 0 HcmV?d00001