This commit is contained in:
琉璃月光
2025-10-22 17:52:29 +08:00
parent c134abf749
commit 1ec9bbab60
18 changed files with 532 additions and 6 deletions

BIN
ailai_pc/1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 333 KiB

BIN
ailai_pc/2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 860 KiB

BIN
ailai_pc/22222.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 733 KiB

BIN
ailai_pc/3.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 725 KiB

Binary file not shown.

BIN
ailai_pc/best1.pt Normal file

Binary file not shown.

134
ailai_pc/detect.py Normal file
View File

@ -0,0 +1,134 @@
import cv2
import numpy as np
from rknnlite.api import RKNNLite
MODEL_PATH = "detect.rknn"
CLASS_NAMES = ["bag"] # 单类
class Yolo11Detector:
def __init__(self, model_path):
self.rknn = RKNNLite(verbose=False)
# 加载 RKNN 模型
ret = self.rknn.load_rknn(model_path)
assert ret == 0, "❌ Load RKNN model failed"
# 初始化运行时(使用 NPU 核心0
ret = self.rknn.init_runtime(core_mask=RKNNLite.NPU_CORE_0)
assert ret == 0, "❌ Init runtime failed"
# 模型输入大小
self.input_size = 640
# YOLO anchors根据你训练的模型
self.anchors = {
8: [[10, 13], [16, 30], [33, 23]],
16: [[30, 61], [62, 45], [59, 119]],
32: [[116, 90], [156, 198], [373, 326]]
}
def preprocess(self, img):
"""高性能预处理:缩放+RGB"""
h, w = img.shape[:2]
scale = min(self.input_size / w, self.input_size / h)
new_w, new_h = int(w * scale), int(h * scale)
img_resized = cv2.resize(img, (new_w, new_h))
canvas = np.full((self.input_size, self.input_size, 3), 114, dtype=np.uint8)
dw, dh = (self.input_size - new_w) // 2, (self.input_size - new_h) // 2
canvas[dh:dh + new_h, dw:dw + new_w, :] = img_resized
img_rgb = cv2.cvtColor(canvas, cv2.COLOR_BGR2RGB)
return np.expand_dims(img_rgb, 0).astype(np.uint8), scale, dw, dh
def postprocess(self, outputs, scale, dw, dh, conf_thresh=0.25, iou_thresh=0.45):
"""解析 YOLO 输出"""
# 注意:根据 RKNN 输出节点选择
preds = outputs[0].reshape(-1, outputs[0].shape[1]) # 假设输出 [1, N, C]
boxes, scores, class_ids = [], [], []
for p in preds:
conf = p[4]
if conf < conf_thresh:
continue
cls_conf = p[5] # 单类模型
score = conf * cls_conf
if score < conf_thresh:
continue
cx, cy, w, h = p[:4]
x1 = (cx - w / 2 - dw) / scale
y1 = (cy - h / 2 - dh) / scale
x2 = (cx + w / 2 - dw) / scale
y2 = (cy + h / 2 - dh) / scale
boxes.append([x1, y1, x2, y2])
scores.append(score)
class_ids.append(0) # 单类
if len(boxes) == 0:
return []
boxes = np.array(boxes)
scores = np.array(scores)
class_ids = np.array(class_ids)
# 简单 NMS
idxs = np.argsort(scores)[::-1]
keep = []
while len(idxs) > 0:
i = idxs[0]
keep.append(i)
if len(idxs) == 1:
break
x1, y1, x2, y2 = boxes[i]
xx1 = np.maximum(x1, boxes[idxs[1:], 0])
yy1 = np.maximum(y1, boxes[idxs[1:], 1])
xx2 = np.minimum(x2, boxes[idxs[1:], 2])
yy2 = np.minimum(y2, boxes[idxs[1:], 3])
inter = np.maximum(0, xx2 - xx1) * np.maximum(0, yy2 - yy1)
area_i = (x2 - x1) * (y2 - y1)
area_j = (boxes[idxs[1:], 2] - boxes[idxs[1:], 0]) * (boxes[idxs[1:], 3] - boxes[idxs[1:], 1])
iou = inter / (area_i + area_j - inter + 1e-6)
idxs = idxs[1:][iou < iou_thresh]
results = []
for i in keep:
results.append({
"box": boxes[i],
"score": scores[i],
"class_id": class_ids[i]
})
return results
def detect(self, img):
img_data, scale, dw, dh = self.preprocess(img)
outputs = self.rknn.inference([img_data])
results = self.postprocess(outputs, scale, dw, dh)
return results
def release(self):
self.rknn.release()
if __name__ == "__main__":
detector = Yolo11Detector(MODEL_PATH)
cap = cv2.VideoCapture(0) # 可以换成图片路径
while True:
ret, frame = cap.read()
if not ret:
break
results = detector.detect(frame)
for r in results:
x1, y1, x2, y2 = map(int, r["box"])
cls_id = r["class_id"]
score = r["score"]
cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2)
cv2.putText(frame, f"{CLASS_NAMES[cls_id]} {score:.2f}", (x1, y1 - 10),
cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0, 255, 0), 2)
cv2.imshow("YOLOv11 Detection", frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
detector.release()
cap.release()

72
ailai_pc/detet_pc.py Normal file
View File

@ -0,0 +1,72 @@
# detect_pt.py
import cv2
import torch
from ultralytics import YOLO
# ======================
# 配置参数
# ======================
MODEL_PATH = 'best.pt' # 你的训练模型路径yolov8n.pt 或你自己训练的)
#IMG_PATH = '/home/hx/开发/ailai_image_obb/ailai_pc/train/192.168.0.234_01_202510141514352.jpg' # 测试图像路径
IMG_PATH = '1.jpg'
OUTPUT_PATH = '/home/hx/开发/ailai_image_obb/ailai_pc/output_pt.jpg' # 可视化结果保存路径
CONF_THRESH = 0.5 # 置信度阈值
CLASS_NAMES = ['bag'] # 你的类别名列表(按训练时顺序)
# 是否显示窗口(适合有 GUI 的 PC
SHOW_IMAGE = True
# ======================
# 主函数
# ======================
def main():
# 检查 CUDA
device = 'cuda' if torch.cuda.is_available() else 'cpu'
print(f"✅ 使用设备: {device}")
# 加载模型
print("➡️ 加载 YOLO 模型...")
model = YOLO(MODEL_PATH) # 自动加载架构和权重
model.to(device)
# 推理
print("➡️ 开始推理...")
results = model(IMG_PATH, imgsz=640, conf=CONF_THRESH, device=device)
# 获取第一张图的结果
r = results[0]
# 获取原始图像BGR
img = cv2.imread(IMG_PATH)
if img is None:
raise FileNotFoundError(f"无法读取图像: {IMG_PATH}")
print("\n📋 检测结果:")
for box in r.boxes:
# 获取数据
xyxy = box.xyxy[0].cpu().numpy() # [x1, y1, x2, y2]
conf = box.conf.cpu().numpy()[0] # 置信度
cls_id = int(box.cls.cpu().numpy()[0]) # 类别 ID
cls_name = CLASS_NAMES[cls_id] # 类别名
x1, y1, x2, y2 = map(int, xyxy)
print(f" 类别: {cls_name}, 置信度: {conf:.3f}, 框: [{x1}, {y1}, {x2}, {y2}]")
# 画框
cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2)
# 画标签
label = f"{cls_name} {conf:.2f}"
cv2.putText(img, label, (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0, 255, 0), 2)
# 保存结果
cv2.imwrite(OUTPUT_PATH, img)
print(f"\n🖼️ 可视化结果已保存: {OUTPUT_PATH}")
# 显示(可选)
if SHOW_IMAGE:
cv2.imshow("YOLOv8 Detection", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
if __name__ == '__main__':
main()

BIN
ailai_pc/output_pt.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 586 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB