diff --git a/models/ResNet50/pokedex_ResNet50.har b/models/ResNet50/pokedex_ResNet50.har new file mode 100644 index 0000000000000000000000000000000000000000..85c905a693c35e13336e3830052e94563bf18630 Binary files /dev/null and b/models/ResNet50/pokedex_ResNet50.har differ diff --git a/models/ResNet50/pokedex_ResNet50.hef b/models/ResNet50/pokedex_ResNet50.hef new file mode 100644 index 0000000000000000000000000000000000000000..2777c495e79169d46660e7824f209f52a5d7a8a2 Binary files /dev/null and b/models/ResNet50/pokedex_ResNet50.hef differ diff --git a/models/ResNet50/pokedex_ResNet50_compiled.har b/models/ResNet50/pokedex_ResNet50_compiled.har new file mode 100644 index 0000000000000000000000000000000000000000..7f6e622d54f9a7a3aa48f1df9ebcda3b4e40315f Binary files /dev/null and b/models/ResNet50/pokedex_ResNet50_compiled.har differ diff --git a/models/ResNet50/pokedex_ResNet50_optimized.har b/models/ResNet50/pokedex_ResNet50_optimized.har new file mode 100644 index 0000000000000000000000000000000000000000..407802a1c153bae96fefc566a253e1a511c8a919 Binary files /dev/null and b/models/ResNet50/pokedex_ResNet50_optimized.har differ diff --git a/models/Xception/pokedex_Xception.onnx b/models/Xception/pokedex_Xception.onnx new file mode 100644 index 0000000000000000000000000000000000000000..87a4669d62753d3a3456a4be322a0abaf60886c9 Binary files /dev/null and b/models/Xception/pokedex_Xception.onnx differ diff --git a/models/Xception/pokedex_Xception_compiled.har b/models/Xception/pokedex_Xception_compiled.har new file mode 100644 index 0000000000000000000000000000000000000000..f7aa083e5e2369352b80163d3916600da307e1db Binary files /dev/null and b/models/Xception/pokedex_Xception_compiled.har differ diff --git a/models/Xception/pokedex_Xception_optimized.har b/models/Xception/pokedex_Xception_optimized.har new file mode 100644 index 0000000000000000000000000000000000000000..9e0cc5fd4dae39f95b4fc1a590f6f555020bcaf2 Binary files /dev/null and b/models/Xception/pokedex_Xception_optimized.har differ diff --git a/python/convert_onnx.py b/python/convert_onnx.py index a90d6d1b941da7cd367a300c02670a3393ddd9ff..041d7fa0926e5b9ee6fd5cb5c21c15bbffc0101b 100644 --- a/python/convert_onnx.py +++ b/python/convert_onnx.py @@ -16,7 +16,7 @@ if args.model == "1": size_2=(1, 224, 224, 3) elif args.model == "2": h5_path = "../models/Xception/pokedex_Xception.h5" - onnx_path = "../models/ResNet50/pokedex_Xception.onnx" + onnx_path = "../models/Xception/pokedex_Xception.onnx" size=(256, 256, 3) size_2=(1, 256, 256, 3) diff --git a/python/pokedex_rpi.py b/python/pokedex_rpi.py index 258de2ed92d93d56edf62a1076cfb7345ac4ab8a..01101404a342540e398fe1959a400730b4ec92f7 100644 --- a/python/pokedex_rpi.py +++ b/python/pokedex_rpi.py @@ -1,60 +1,75 @@ -import cv2 -import numpy as np import json -from hailo_platform.pyhailort import HailoRT import argparse +import numpy as np +from picamera2 import Picamera2 +from picamera2.devices.hailo import Hailo +import cv2 +import os -# --- WHAT ? --- -parser = argparse.ArgumentParser(description="WHAT ?!") +# --- Argparse --- +parser = argparse.ArgumentParser(description="Pokémon Classifier Inference with Hailo-8") parser.add_argument("--model", choices=["1", "2"], required=True, help="1 = ResNet50, 2 = Xception") args = parser.parse_args() -# Paths +# --- Paths & Input Sizes --- if args.model == "1": hef_path = "../models/ResNet50/pokedex_ResNet50.hef" json_path = "../models/ResNet50/class_names.json" - size=(224,224) + input_shape = (224, 224) elif args.model == "2": hef_path = "../models/Xception/pokedex_Xception.hef" json_path = "../models/Xception/class_names.json" - size=(256,256) + input_shape = (256, 256) +else: + raise ValueError("Invalid model selection") -# Load class names +# --- Load class names --- with open(json_path, "r") as f: class_names = json.load(f) -device = HailoRT.Device() -hef = HailoRT.Hef(hef_path) -configured_network_group = device.create_hef_group(hef) -input_vstream_info = configured_network_group.get_input_vstream_infos()[0] -output_vstream_info = configured_network_group.get_output_vstream_infos()[0] - -# --- Open webcam --- -cap = cv2.VideoCapture(0) -if not cap.isOpened(): - print("-- Unable to open webcam") - exit() - -print("-- Taking picture...") -ret, frame = cap.read() -cap.release() - -if not ret: - print("-- Failed to capture image") - exit() - -# --- Preprocess image --- -image = cv2.resize(frame, size) -image = image.astype(np.float32) / 255.0 # Normalize to [0, 1] -image = np.expand_dims(image, axis=0) # Add batch dimension -image = np.transpose(image, (0, 3, 1, 2)) # NHWC ? NCHW if required (check your model) - -# --- Inference --- -with HailoRT.VirtualStreams(input_vstream_info, output_vstream_info, configured_network_group) as (input_vstreams, output_vstreams): - input_vstreams[0].send(image) - output_data = output_vstreams[0].recv() - -# --- Postprocess --- -predicted_idx = int(np.argmax(output_data)) -predicted_name = class_names[predicted_idx] -print(f"-- Predicted Pokémon: {predicted_name}") +# --- Hailo Inference with PiCamera2 --- +with Hailo(hef_path) as hailo: + model_h, model_w, model_c = hailo.get_input_shape() + print(f"-- Model input shape from Hailo: {(model_h, model_w, model_c)}") + print(f"-- Input format: {hailo.get_input_format()}") + print(f"-- Expected input buffer size: {hailo.get_input_frame_size()}") + + + picam2 = Picamera2() + config = picam2.create_still_configuration( + main={"size": input_shape, "format": "RGB888"}, + lores=None, + display=None + ) + picam2.configure(config) + picam2.start() + + print("-- Capturing image...") + frame = picam2.capture_array() + print(f"-- Captured frame shape: {frame.shape}") + + # Optional: show image + try: + cv2.imshow("Captured Image", frame) + print("-- Press any key to continue...") + cv2.waitKey(0) + cv2.destroyAllWindows() + except cv2.error: + print("-- GUI display failed, saving and showing with feh instead...") + output_path = "/tmp/captured.png" + cv2.imwrite(output_path, frame) + os.system(f"feh --fullscreen {output_path}") + + # --- Preprocess image --- + image = frame.astype(np.float32) / 255.0 # Normalize to [0, 1] + image = np.expand_dims(image, axis=0) # Add batch dimension → (1, H, W, C) + image = np.transpose(image, (0, 3, 1, 2)) # NHWC → NCHW + image = np.ascontiguousarray(image) # Ensure buffer is C-contiguous + + + print("-- Running inference...") + inference_results = hailo.run(image) + + predicted_idx = int(np.argmax(inference_results)) + predicted_name = class_names[predicted_idx] + print(f"-- Predicted Pokémon: {predicted_name}")