from pathlib import Path
import matplotlib.path as mat
from utils.general import strtolstl
from utils.general import compute_IOU
from torchvision import transforms
from PIL import Image
import torch
import torch.nn.functional as F
import numpy as np
from ultralytics.engine.results import Results
import torch.nn as nn
from shapely.geometry import Point
from ultralytics.utils import ops
from shapely.geometry.polygon import Polygon
from pydantic import BaseModel
mean, std = [0.485, 0.456, 0.406], [0.229, 0.224, 0.225]
test = transforms.Compose([transforms.Resize((224, 224)),
                           # transforms.CenterCrop(224),
                           transforms.ToTensor(),
                           transforms.Normalize(mean=mean, std=std)
                           ])
def clapre(modelcla, claimg, clapoint):
    imgten = torch.stack(claimg, dim=0)
    clapoint = torch.stack(clapoint, dim=0)
    imgten = imgten.to(0)
    result = modelcla(imgten)
    result = F.softmax(result)
    print(result)
    index = result.argmax(1)
    index = index.cpu().numpy()
    index = np.argwhere(index < 5)
    index = index.reshape(-1)
    print(index)
    if len(index) > 0:
        print(clapoint[index])
        return clapoint[index]
    else:
        return None

class Model(nn.Module):
    def __init__(self, A, nnode, nfeature, nclass):
        super().__init__()
        self.fc1 = nn.Linear(nnode * nfeature, 512)
        self.fc2 = nn.Linear(512, nclass)
    def forward(self, x):
        x = x.view(-1, int(x.size(1) * x.size(2)))
        x = F.relu(self.fc1(x))
        x = F.dropout(x, 0.7, training=self.training)
        return self.fc2(x)
def extract_keypoint(get_keypoint, keypoint):
    # nose
    nose_x, nose_y = keypoint[get_keypoint.NOSE]
    # eye
    # left_eye_x, left_eye_y = keypoint[get_keypoint.LEFT_EYE]
    # right_eye_x, right_eye_y = keypoint[get_keypoint.RIGHT_EYE]
    # # ear
    # left_ear_x, left_ear_y = keypoint[get_keypoint.LEFT_EAR]
    # right_ear_x, right_ear_y = keypoint[get_keypoint.RIGHT_EAR]
    # shoulder
    left_shoulder_x, left_shoulder_y = keypoint[get_keypoint.LEFT_SHOULDER]
    right_shoulder_x, right_shoulder_y = keypoint[get_keypoint.RIGHT_SHOULDER]
    # elbow
    left_elbow_x, left_elbow_y = keypoint[get_keypoint.LEFT_ELBOW]
    right_elbow_x, right_elbow_y = keypoint[get_keypoint.RIGHT_ELBOW]
    # wrist
    left_wrist_x, left_wrist_y = keypoint[get_keypoint.LEFT_WRIST]
    right_wrist_x, right_wrist_y = keypoint[get_keypoint.RIGHT_WRIST]
    # hip
    left_hip_x, left_hip_y = keypoint[get_keypoint.LEFT_HIP]
    right_hip_x, right_hip_y = keypoint[get_keypoint.RIGHT_HIP]
    # knee
    left_knee_x, left_knee_y = keypoint[get_keypoint.LEFT_KNEE]
    right_knee_x, right_knee_y = keypoint[get_keypoint.RIGHT_KNEE]
    # ankle
    left_ankle_x, left_ankle_y = keypoint[get_keypoint.LEFT_ANKLE]
    right_ankle_x, right_ankle_y = keypoint[get_keypoint.RIGHT_ANKLE]
    return [
        nose_x, nose_y,
        left_shoulder_x, left_shoulder_y,
        right_shoulder_x, right_shoulder_y,
        left_elbow_x, left_elbow_y,
        right_elbow_x, right_elbow_y,
        left_wrist_x, left_wrist_y,
        right_wrist_x, right_wrist_y,
        left_hip_x, left_hip_y,
        right_hip_x, right_hip_y,
        left_knee_x, left_knee_y,
        right_knee_x, right_knee_y,
        left_ankle_x, left_ankle_y,
        right_ankle_x, right_ankle_y
    ]
class GetKeypoint(BaseModel):
    NOSE: int = 0
    LEFT_EYE: int = 1
    RIGHT_EYE: int = 2
    LEFT_EAR: int = 3
    RIGHT_EAR: int = 4
    LEFT_SHOULDER: int = 5
    RIGHT_SHOULDER: int = 6
    LEFT_ELBOW: int = 7
    RIGHT_ELBOW: int = 8
    LEFT_WRIST: int = 9
    RIGHT_WRIST: int = 10
    LEFT_HIP: int = 11
    RIGHT_HIP: int = 12
    LEFT_KNEE: int = 13
    RIGHT_KNEE: int = 14
    LEFT_ANKLE: int = 15
    RIGHT_ANKLE: int = 16

class Helmet:
    def __init__(self):
        self.flag = False
    def getflag(self, det, persondet, annotator, fence=0, point=None, names=None, rname=None, num=1, channel=None):
        # print(type(det))
        self.flag = False
        for *xyxy, conf, cls in reversed(det):
            c = int(cls)
            labelname = names[c]
            if labelname in rname:
                if fence == 1:
                    pointa = strtolstl(point)
                    for poi in pointa:
                        p1 = (int(xyxy[0].cpu().item() + (xyxy[2].cpu().item() - xyxy[0].cpu().item()) / 3),
                              xyxy[3].cpu().item())
                        p2 = (int(xyxy[0].cpu().item() + (xyxy[2].cpu().item() - xyxy[0].cpu().item()) / 3 * 2),
                              xyxy[3].cpu().item())
                        pt = [p1, p2]
                        inflag = mat.Path(poi).contains_points(pt)
                        if inflag.any():
                            if persondet is None:
                                self.flag = True
                                # c = int(cls)  # integer class
                                # label = f'{self.names[c]} {conf:.2f}'
                                label = None
                                annotator.box_label(xyxy, None, color=(0, 0, 255))
                            else:
                                for person in persondet:
                                    personinflag = mat.Path(person).contains_points(pt)
                                    if personinflag.any():
                                        annotator.box_label(xyxy, None, color=(0, 0, 255))
                                        self.flag = True
                else:
                    if persondet is None:
                        self.flag = True
                        # c = int(cls)  # integer class
                        # label = f'{self.names[c]} {conf:.2f}'
                        label = None
                        annotator.box_label(xyxy, None, color=(0, 0, 255))
                    else:
                        for person in persondet:
                            p1 = (int(xyxy[0].cpu().item() + (xyxy[2].cpu().item() - xyxy[0].cpu().item()) / 3),
                                  xyxy[3].cpu().item())
                            p2 = (int(xyxy[0].cpu().item() + (xyxy[2].cpu().item() - xyxy[0].cpu().item()) / 3 * 2),
                                  xyxy[3].cpu().item())
                            pt = [p1, p2]
                            personinflag = mat.Path(person).contains_points(pt)
                            if personinflag.any():
                                annotator.box_label(xyxy, None, color=(0, 0, 255))
                                self.flag = True
        return self.flag

class Uniform:
    def __init__(self):
        self.flag = False
    def getflag(self, det, persondet, annotator, fence=0, point=None, names=None, rname=None, num=1, channel=None):
        self.flag = False
        for *xyxy, conf, cls in reversed(det):
            c = int(cls)
            labelname = names[c]
            if labelname in rname:
                if fence == 1:
                    pointa = strtolstl(point)
                    for poi in pointa:
                        p1 = (int(xyxy[0].cpu().item() + (xyxy[2].cpu().item() - xyxy[0].cpu().item()) / 3),
                              xyxy[3].cpu().item())
                        p2 = (int(xyxy[0].cpu().item() + (xyxy[2].cpu().item() - xyxy[0].cpu().item()) / 3 * 2),
                              xyxy[3].cpu().item())
                        pt = [p1, p2]
                        inflag = mat.Path(poi).contains_points(pt)
                        if inflag.any():
                            if persondet is None:
                                self.flag = True
                                # c = int(cls)  # integer class
                                # label = f'{self.names[c]} {conf:.2f}'
                                label = None
                                annotator.box_label(xyxy, None, color=(0, 0, 255))
                            else:
                                for person in persondet:
                                    p1 = (int(xyxy[0].cpu().item() + (xyxy[2].cpu().item() - xyxy[0].cpu().item()) / 3),
                                          xyxy[3].cpu().item())
                                    p2 = (
                                        int(xyxy[0].cpu().item() + (
                                                    xyxy[2].cpu().item() - xyxy[0].cpu().item()) / 3 * 2),
                                        xyxy[3].cpu().item())
                                    pt = [p1, p2]
                                    personinflag = mat.Path(person).contains_points(pt)
                                    if personinflag.any():
                                        annotator.box_label(xyxy, None, color=(0, 0, 255))
                                        self.flag = True
                else:
                    if persondet is None:
                        self.flag = True
                        # c = int(cls)  # integer class
                        # label = f'{self.names[c]} {conf:.2f}'
                        label = None
                        annotator.box_label(xyxy, None, color=(0, 0, 255))
                    else:
                        for person in persondet:
                            p1 = (int(xyxy[0].cpu().item() + (xyxy[2].cpu().item() - xyxy[0].cpu().item()) / 3),
                                  xyxy[3].cpu().item())
                            p2 = (int(xyxy[0].cpu().item() + (xyxy[2].cpu().item() - xyxy[0].cpu().item()) / 3 * 2),
                                  xyxy[3].cpu().item())
                            pt = [p1, p2]
                            personinflag = mat.Path(person).contains_points(pt)
                            if personinflag.any():
                                annotator.box_label(xyxy, None, color=(0, 0, 255))
                                self.flag = True
        return self.flag

class Fall:
    def __init__(self):
        self.flag = False
    def getflag(self, det, persondet, annotator, fence=0, point=None, names=None, rname=None, num=1, channel=None):
        self.flag = False
        for *xyxy, conf, cls in reversed(det):
            c = int(cls)
            labelname = names[c]
            if labelname in rname:
                if fence == 1:
                    pointa = strtolstl(point)
                    for poi in pointa:
                        p1 = (int(xyxy[0].cpu().item() + (xyxy[2].cpu().item() - xyxy[0].cpu().item()) / 3),
                              xyxy[3].cpu().item())
                        p2 = (int(xyxy[0].cpu().item() + (xyxy[2].cpu().item() - xyxy[0].cpu().item()) / 3 * 2),
                              xyxy[3].cpu().item())
                        pt = [p1, p2]
                        inflag = mat.Path(poi).contains_points(pt)
                        if inflag.any():
                            if persondet is None:
                                self.flag = True
                                # c = int(cls)  # integer class
                                # label = f'{self.names[c]} {conf:.2f}'
                                label = None
                                annotator.box_label(xyxy, None, color=(0, 0, 255))
                            else:
                                for person in persondet:
                                    personinflag = mat.Path(person).contains_points(pt)
                                    if personinflag.any():
                                        annotator.box_label(xyxy, None, color=(0, 0, 255))
                                        self.flag = True
                else:
                    if persondet is None:
                        self.flag = True
                        # c = int(cls)  # integer class
                        # label = f'{self.names[c]} {conf:.2f}'
                        label = None
                        annotator.box_label(xyxy, None, color=(0, 0, 255))
                    else:
                        for person in persondet:
                            p1 = (int(xyxy[0].cpu().item() + (xyxy[2].cpu().item() - xyxy[0].cpu().item()) / 3),
                                  xyxy[3].cpu().item())
                            p2 = (int(xyxy[0].cpu().item() + (xyxy[2].cpu().item() - xyxy[0].cpu().item()) / 3 * 2),
                                  xyxy[3].cpu().item())
                            pt = [p1, p2]
                            personinflag = mat.Path(person).contains_points(pt)
                            if personinflag.any():
                                annotator.box_label(xyxy, None, color=(0, 0, 255))
                                self.flag = True
        return self.flag

class newFall:
    def __init__(self):
        self.flag = False
        self.get_keypoint = GetKeypoint()
        self.pose_classfier_model = Model(None, 13, 2, 2)
        self.pose_classfier_model.load_state_dict(torch.load("/home/h3c/yolo/fallcls.pt"))
        self.pose_classfier_model.eval()
        self.pose_classfier_model.to(0)
    def getflag(self, det, persondet, annotator, fence=0, point=None, names=None, rname=None, num=1, imshape=None,
                channel=None):
        self.flag = False
        kptshape = [17, 3]
        print(f'len = {len(det)}')
        pred_kpts = det[:, 6:].view(len(det), *kptshape) if len(det) else det[:, 6:]
        pred_kpts = ops.scale_coords(imshape, pred_kpts, annotator.result().shape)
        results = Results(annotator.result(), path=None, names=names, boxes=det[:, :6], keypoints=pred_kpts)
        # results.save("fall.jpg")
        print(results.boxes)
        if len(point) > 1:
            self.polygon_areas = [Polygon(strtolstl(point)[0])]
            print(self.polygon_areas)
        else:
            self.polygon_areas = None
        tmppersondet = []
        if self.polygon_areas is not None:
            for person in persondet:
                polygon_box = Polygon(
                    [(person[0], person[1]), (person[2], person[3]), (person[4], person[5]), (person[6], person[7])])
                intersection_areas = [polygon_area.intersection(polygon_box).area for polygon_area in
                                      self.polygon_areas]
                if sum(intersection_areas) == 0:
                    continue
                intersection_areas_ratio = sorted(
                    [intersection_area / polygon_box.area for intersection_area in intersection_areas])
                # print(intersection_areas_ratio)
                if intersection_areas_ratio[-1] < 0.9:
                    continue
                tmppersondet.append(person)
            persondet = tmppersondet
        boxes = results.boxes.xyxy.cpu().numpy().tolist()
        confs = results.boxes.conf.cpu().numpy().tolist()
        all_keypoints = results.keypoints.data.cpu().numpy().tolist()
        pose_classfier_results = []
        for box, conf, keypoints in zip(boxes, confs, all_keypoints):
            iouflag = False
            for personbox in persondet:
                person = [personbox[0], personbox[1], personbox[4], personbox[5]]
                iou, _ = compute_IOU(box, person)
                print(f'judgeiou = {iou}')
                if iou > 0.5:
                    iouflag = True
                    break;
            if not iouflag:
                break
            x1, y1, x2, y2 = box
            x, y, w, h = x1, y1, x2 - x1, y2 - y1
            n_keypoints = [[(kp[0] - x) / w - 0.5, (kp[1] - y) / h - 0.5] if kp[0] > 0 and kp[1] > 0 else kp[:2] for kp
                           in keypoints]
            n_keypoints = extract_keypoint(self.get_keypoint, n_keypoints)
            if n_keypoints[-12:].count(0) >= 2 * 2:
                continue
            if n_keypoints.count(0) >= 4 * 2:
                continue
            if w < h:
                continue
            pose_data = torch.Tensor([n_keypoints]).to(0)
            pose_data = pose_data.reshape(1, 13, 2)
            with torch.no_grad():
                p = self.pose_classfier_model(pose_data)
                prob = F.softmax(p)
                index = prob.argmax()
                if index == 0:
                    score = float(prob[0][index].cpu().numpy())
                    pose_classfier_results.append(box)
            if len(pose_classfier_results) > 0:
                for xyxy in pose_classfier_results:
                    annotator.box_label(xyxy, None, color=(0, 0, 255))
                    # cv2.imread('fall.jpg',annotator.result())
                import cv2
                cv2.imwrite('fall.jpg', annotator.result())
                self.flag = True
        return self.flag

class Personcount:
    def __init__(self):
        self.flag = False
    def getflag(self, det, persondet, annotator, fence=0, point=None, names=None, rname=None, num=1, channel=None):
        self.flag = False
        detnum = 0
        for *xyxy, conf, cls in reversed(det):
            c = int(cls)
            labelname = names[c]
            if labelname in rname:
                if fence == 1:
                    pointa = strtolstl(point)
                    for poi in pointa:
                        p1 = (int(xyxy[0].cpu().item() + (xyxy[2].cpu().item() - xyxy[0].cpu().item()) / 3),
                              xyxy[3].cpu().item())
                        p2 = (int(xyxy[0].cpu().item() + (xyxy[2].cpu().item() - xyxy[0].cpu().item()) / 3 * 2),
                              xyxy[3].cpu().item())
                        pt = [p1, p2]
                        inflag = mat.Path(poi).contains_points(pt)
                        if inflag.any():
                            if persondet is None:
                                # self.flag = True
                                detnum = detnum + 1
                                # c = int(cls)  # integer class
                                # label = f'{self.names[c]} {conf:.2f}'
                                label = None
                                annotator.box_label(xyxy, None, color=(0, 0, 255))
                            else:
                                for person in persondet:
                                    personinflag = mat.Path(person).contains_points(pt)
                                    if personinflag.any():
                                        detnum = detnum + 1
                                        annotator.box_label(xyxy, None, color=(0, 0, 255))
                                        # self.flag = True
                else:
                    if persondet is None:
                        # self.flag = True
                        detnum = detnum + 1
                        # c = int(cls)  # integer class
                        # label = f'{self.names[c]} {conf:.2f}'
                        label = None
                        annotator.box_label(xyxy, None, color=(0, 0, 255))
                    else:
                        for person in persondet:
                            p1 = (int(xyxy[0].cpu().item() + (xyxy[2].cpu().item() - xyxy[0].cpu().item()) / 3),
                                  xyxy[3].cpu().item())
                            p2 = (int(xyxy[0].cpu().item() + (xyxy[2].cpu().item() - xyxy[0].cpu().item()) / 3 * 2),
                                  xyxy[3].cpu().item())
                            pt = [p1, p2]
                            personinflag = mat.Path(person).contains_points(pt)
                            if personinflag.any():
                                detnum = detnum + 1
                                annotator.box_label(xyxy, None, color=(0, 0, 255))
                                # self.flag = True
        if detnum >= num:
            self.flag = True
        return self.flag

class Arm:
    def __init__(self):
        self.flag = False
    def getflag(self, det, persondet, annotator, fence=0, point=None, names=None, rname=None, num=1, channel=None):
        self.flag = False
        for *xyxy, conf, cls in reversed(det):
            c = int(cls)
            labelname = names[c]
            if labelname in rname:
                if fence == 1:
                    pointa = strtolstl(point)
                    for poi in pointa:
                        p1 = (int(xyxy[0].cpu().item() + (xyxy[2].cpu().item() - xyxy[0].cpu().item()) / 3),
                              xyxy[3].cpu().item())
                        p2 = (int(xyxy[0].cpu().item() + (xyxy[2].cpu().item() - xyxy[0].cpu().item()) / 3 * 2),
                              xyxy[3].cpu().item())
                        pt = [p1, p2]
                        inflag = mat.Path(poi).contains_points(pt)
                        if inflag.any():
                            if persondet is None:
                                self.flag = True
                                # c = int(cls)  # integer class
                                # label = f'{self.names[c]} {conf:.2f}'
                                label = None
                                annotator.box_label(xyxy, None, color=(0, 0, 255))
                            else:
                                for person in persondet:
                                    personinflag = mat.Path(person).contains_points(pt)
                                    if personinflag.any():
                                        annotator.box_label(xyxy, None, color=(0, 0, 255))
                                        self.flag = True
                else:
                    if persondet is None:
                        self.flag = True
                        # c = int(cls)  # integer class
                        # label = f'{self.names[c]} {conf:.2f}'
                        label = None
                        annotator.box_label(xyxy, None, color=(0, 0, 255))
                    else:
                        for person in persondet:
                            p1 = (int(xyxy[0].cpu().item() + (xyxy[2].cpu().item() - xyxy[0].cpu().item()) / 3),
                                  xyxy[3].cpu().item())
                            p2 = (int(xyxy[0].cpu().item() + (xyxy[2].cpu().item() - xyxy[0].cpu().item()) / 3 * 2),
                                  xyxy[3].cpu().item())
                            pt = [p1, p2]
                            personinflag = mat.Path(np.array(person).reshape(-1, 2)).contains_points(pt)
                            if personinflag.any():
                                annotator.box_label(xyxy, None, color=(0, 0, 255))
                                self.flag = True
        return self.flag

class Bag:
    def __init__(self):
        self.flag = False
    def getflag(self, det, persondet, annotator, fence=0, point=None, names=None, rname=None, num=1, channel=None):
        self.flag = False
        for *xyxy, conf, cls in reversed(det):
            c = int(cls)
            labelname = names[c]
            if labelname in rname:
                if fence == 1:
                    pointa = strtolstl(point)
                    for poi in pointa:
                        p1 = (int(xyxy[0].cpu().item() + (xyxy[2].cpu().item() - xyxy[0].cpu().item()) / 3),
                              xyxy[3].cpu().item())
                        p2 = (int(xyxy[0].cpu().item() + (xyxy[2].cpu().item() - xyxy[0].cpu().item()) / 3 * 2),
                              xyxy[3].cpu().item())
                        pt = [p1, p2]
                        inflag = mat.Path(poi).contains_points(pt)
                        if inflag.any():
                            if persondet is None:
                                self.flag = True
                                # c = int(cls)  # integer class
                                # label = f'{self.names[c]} {conf:.2f}'
                                label = None
                                annotator.box_label(xyxy, None, color=(0, 0, 255))
                            else:
                                for person in persondet:
                                    personinflag = mat.Path(person).contains_points(pt)
                                    if personinflag.any():
                                        annotator.box_label(xyxy, None, color=(0, 0, 255))
                                        self.flag = True
                else:
                    if persondet is None:
                        self.flag = True
                        # c = int(cls)  # integer class
                        # label = f'{self.names[c]} {conf:.2f}'
                        label = None
                        annotator.box_label(xyxy, None, color=(0, 0, 255))
                    else:
                        for person in persondet:
                            p1 = (int(xyxy[0].cpu().item() + (xyxy[2].cpu().item() - xyxy[0].cpu().item()) / 3),
                                  xyxy[3].cpu().item())
                            p2 = (int(xyxy[0].cpu().item() + (xyxy[2].cpu().item() - xyxy[0].cpu().item()) / 3 * 2),
                                  xyxy[3].cpu().item())
                            pt = [p1, p2]
                            personinflag = mat.Path(person).contains_points(pt)
                            if personinflag.any():
                                annotator.box_label(xyxy, None, color=(0, 0, 255))
                                self.flag = True
        return self.flag

class Cross:
    def __init__(self):
        self.flag = False
    def getflag(self, det, persondet, annotator, fence=0, point=None, names=None, rname=None, num=1, channel=None):
        self.flag = False
        detnum = 0
        for *xyxy, conf, cls in reversed(det):
            c = int(cls)
            labelname = names[c]
            if labelname in rname:
                if fence == 1:
                    pointa = strtolstl(point)
                    for poi in pointa:
                        p1 = (int(xyxy[0].cpu().item() + (xyxy[2].cpu().item() - xyxy[0].cpu().item()) / 3),
                              xyxy[3].cpu().item())
                        p2 = (int(xyxy[0].cpu().item() + (xyxy[2].cpu().item() - xyxy[0].cpu().item()) / 3 * 2),
                              xyxy[3].cpu().item())
                        pt = [p1, p2]
                        inflag = mat.Path(poi).contains_points(pt)
                        if inflag.any():
                            if persondet is None:
                                detnum = detnum + 1
                                self.flag = True
                                # c = int(cls)  # integer class
                                # label = f'{self.names[c]} {conf:.2f}'
                                label = None
                                annotator.box_label(xyxy, None, color=(0, 0, 255))
                            else:
                                for person in persondet:
                                    personinflag = mat.Path(person).contains_points(pt)
                                    if personinflag.any():
                                        detnum = detnum + 1
                                        annotator.box_label(xyxy, None, color=(0, 0, 255))
                                        self.flag = True
                else:
                    if persondet is None:
                        self.flag = True
                        # c = int(cls)  # integer class
                        # label = f'{self.names[c]} {conf:.2f}'
                        detnum = detnum + 1
                        label = None
                        annotator.box_label(xyxy, None, color=(0, 0, 255))
                    else:
                        for person in persondet:
                            p1 = (int(xyxy[0].cpu().item() + (xyxy[2].cpu().item() - xyxy[0].cpu().item()) / 3),
                                  xyxy[3].cpu().item())
                            p2 = (int(xyxy[0].cpu().item() + (xyxy[2].cpu().item() - xyxy[0].cpu().item()) / 3 * 2),
                                  xyxy[3].cpu().item())
                            pt = [p1, p2]
                            personinflag = mat.Path(person).contains_points(pt)
                            if personinflag.any():
                                detnum = detnum + 1
                                annotator.box_label(xyxy, None, color=(0, 0, 255))
                                self.flag = True
        return self.flag

class Extinguisher:
    def __init__(self):
        self.flag = False
    def getflag(self, det, persondet, annotator, fence=0, point=None, names=None, rname=None, num=1, channel=None):
        self.flag = False
        for *xyxy, conf, cls in reversed(det):
            c = int(cls)
            labelname = names[c]
            if labelname in rname:
                if fence == 1:
                    pointa = strtolstl(point)
                    for poi in pointa:
                        p1 = (int(xyxy[0].cpu().item() + (xyxy[2].cpu().item() - xyxy[0].cpu().item()) / 3),
                              xyxy[3].cpu().item())
                        p2 = (int(xyxy[0].cpu().item() + (xyxy[2].cpu().item() - xyxy[0].cpu().item()) / 3 * 2),
                              xyxy[3].cpu().item())
                        pt = [p1, p2]
                        inflag = mat.Path(poi).contains_points(pt)
                        if inflag.any():
                            if persondet is None:
                                self.flag = True
                                # c = int(cls)  # integer class
                                # label = f'{self.names[c]} {conf:.2f}'
                                label = None
                                annotator.box_label(xyxy, None, color=(0, 0, 255))
                            else:
                                for person in persondet:
                                    personinflag = mat.Path(person).contains_points(pt)
                                    if personinflag.any():
                                        annotator.box_label(xyxy, None, color=(0, 0, 255))
                                        self.flag = True
                else:
                    if persondet is None:
                        self.flag = True
                        # c = int(cls)  # integer class
                        # label = f'{self.names[c]} {conf:.2f}'
                        label = None
                        annotator.box_label(xyxy, None, color=(0, 0, 255))
                    else:
                        for person in persondet:
                            p1 = (int(xyxy[0].cpu().item() + (xyxy[2].cpu().item() - xyxy[0].cpu().item()) / 3),
                                  xyxy[3].cpu().item())
                            p2 = (int(xyxy[0].cpu().item() + (xyxy[2].cpu().item() - xyxy[0].cpu().item()) / 3 * 2),
                                  xyxy[3].cpu().item())
                            pt = [p1, p2]
                            personinflag = mat.Path(person).contains_points(pt)
                            if personinflag.any():
                                annotator.box_label(xyxy, None, color=(0, 0, 255))
                                self.flag = True
        return self.flag

def calculate_iou(box1, box2):
    # 计算交集区域 也就是找到次左上 次右下
    x1_int = max(box1[0], box2[0])
    y1_int = max(box1[1], box2[1])
    x2_int = min(box1[2], box2[2])
    y2_int = min(box1[3], box2[3])
    # 交集区域的宽高
    width_int = max(0, x2_int - x1_int)
    height_int = max(0, y2_int - y1_int)
    area_int = width_int * height_int
    # 计算两个框的面积
    area_box1 = (box1[2] - box1[0]) * (box1[3] - box1[1])
    area_box2 = (box2[2] - box2[0]) * (box2[3] - box1[1])
    # 计算并集面积
    # area_union = area_box1 + area_box2 - area_int
    area_union = (box2[2] - box2[0]) * (box2[3] - box2[1])
    # 计算IoU
    iou = area_int / area_union if area_union > 0 else 0
    return iou

def check_cls4_overlap(person_box, target_box, cls4_boxes):
    """
    检查是否有 cls4 物体在目标框与人物框交集区域内，并计算交集面积与 cls4 物体面积的重叠比率。
    返回重叠比率最大值以及其对应的交集区域坐标和 cls4 框。
    参数:
    person_box (tuple): 人物框 (x_min, y_min, x_max, y_max)
    target_box (tuple): 目标框 (x_min, y_min, x_max, y_max)
    cls4_boxes (list): cls4 物体框的列表，每个框为 (x_min, y_min, x_max, y_max)
    返回:
    tuple:
        - 最大的重叠比率 (float)，如果没有符合条件的物体则为 None。
        - 最大重叠比率对应的交集区域的坐标 (inter_x1, inter_y1)。
        - 对应的 cls4 框 (tuple)，如果没有符合条件的物体则为 None。
    """
    # 计算目标框与人物框的交集区域
    min_x = max(person_box[0], target_box[0])
    min_y = max(person_box[1], target_box[1])
    max_x = min(person_box[2], target_box[2])
    max_y = min(person_box[3], target_box[3])
    target_area = (min_x, min_y, max_x, max_y)  # 交集区域
    max_overlap_ratio = -1  # 用于存储最大的重叠比率 这设置为-1有助于区别是否计算了
    best_inter_x1 = 0  # 用于存储最大重叠比率对应的交集坐标
    best_inter_y1 = 0
    best_cls4_box = []  # 用于存储对应的 cls4 框 不能初始化为整数0 整数不可迭代 后序不能添加
    # 检查是否有 cls4 物体在交集区域内
    for cls4_box in cls4_boxes:
        # 判断 cls4 框是否与交集区域有交集
        inter_x1 = max(cls4_box[0], target_area[0])
        inter_y1 = max(cls4_box[1], target_area[1])
        inter_x2 = min(cls4_box[2], target_area[2])
        inter_y2 = min(cls4_box[3], target_area[3])
        if inter_x1 < inter_x2 and inter_y1 < inter_y2:
            # 计算交集区域的面积
            intersection_area = (inter_x2 - inter_x1) * (inter_y2 - inter_y1)
            # print("交集的面积", intersection_area)
            # 计算 cls4_box 的面积
            cls4_area = (cls4_box[2] - cls4_box[0]) * (cls4_box[3] - cls4_box[1])
            # print("cls4_area的面积是", cls4_area)
            # 计算交集区域占 cls4_box 面积的比例
            overlap_ratio = intersection_area / cls4_area
            # 更新最大重叠比率及其相关信息
            if max_overlap_ratio == 0 or overlap_ratio > max_overlap_ratio:
                max_overlap_ratio = overlap_ratio
                best_inter_x1 = inter_x1
                best_inter_y1 = inter_y1
                best_cls4_box = cls4_box
    return max_overlap_ratio, (best_inter_x1, best_inter_y1), best_cls4_box

class Persontre1:
    def __init__(self):
        self.flag = False
        self.classifier_model = torch.load('/home/h3c/yolo/persontrecls.pt')
    def getflag(self, det, persondet, annotator, fence=0, point=None, names=None, rname=None, num=1, im0=None,
                channel=None):
        self.flag = False
        dirp = {}
        dirf = {}
        for *xyxy, conf, cls in reversed(det):
            c = int(cls)
            labelname = names[c]
            if labelname in rname:
                if fence == 1:
                    pointa = strtolstl(point)
                    for poi in pointa:
                        p1 = (int(xyxy[0].cpu().item() + (xyxy[2].cpu().item() - xyxy[0].cpu().item()) / 3),
                              xyxy[3].cpu().item())
                        p2 = (int(xyxy[0].cpu().item() + (xyxy[2].cpu().item() - xyxy[0].cpu().item()) / 3 * 2),
                              xyxy[3].cpu().item())
                        pt = [p1, p2]
                        inflag = mat.Path(poi).contains_points(pt)
                        if inflag.any():
                            if persondet is None:
                                self.flag = True
                                # c = int(cls)  # integer class
                                # label = f'{self.names[c]} {conf:.2f}'
                                label = None
                            if c == 0:
                                dirp.setdefault(0, [])
                                dirp[0].append(xyxy)
                            elif c in [1, 2]:
                                dirp.setdefault(1, [])
                                dirp[1].append(xyxy)
                                dirf.setdefault(1, [])
                                dirf[1].append(xyxy)
                            elif c == 3:
                                dirp.setdefault(1, [])
                                dirp[1].append(xyxy)
                            elif c == 4:
                                dirf.setdefault(0, [])
                                dirf[0].append(xyxy)
                                # annotator.box_label(xyxy, None, color=(0, 0, 255))
                            else:
                                for person in persondet:
                                    personinflag = mat.Path(person).contains_points(pt)
                                    if personinflag.any():
                                        # annotator.box_label(xyxy, None, color=(0, 0, 255))
                                        # self.flag = True
                                        if c == 0:
                                            dirp.setdefault(0, [])
                                            dirp[0].append(xyxy)
                                        elif c in [1, 2]:
                                            dirp.setdefault(1, [])
                                            dirp[1].append(xyxy)
                                            dirf.setdefault(1, [])
                                            dirf[1].append(xyxy)
                                        elif c == 3:
                                            dirp.setdefault(1, [])
                                            dirp[1].append(xyxy)
                                        elif c == 4:
                                            dirf.setdefault(0, [])
                                            dirf[0].append(xyxy)
                else:
                    if persondet is None:
                        # self.flag = True
                        # c = int(cls)  # integer class
                        # label = f'{self.names[c]} {conf:.2f}'
                        # label = None
                        # annotator.box_label(xyxy, None, color=(0, 0, 255))
                        if c == 0:
                            dirp.setdefault(0, [])
                            dirp[0].append(xyxy)
                        elif c in [1, 2]:
                            dirp.setdefault(1, [])
                            dirp[1].append(xyxy)
                            dirf.setdefault(1, [])
                            dirf[1].append(xyxy)
                        elif c == 3:
                            dirp.setdefault(1, [])
                            dirp[1].append(xyxy)
                        elif c == 4:
                            dirf.setdefault(0, [])
                            dirf[0].append(xyxy)
                    else:
                        for person in persondet:
                            p1 = (int(xyxy[0].cpu().item() + (xyxy[2].cpu().item() - xyxy[0].cpu().item()) / 3),
                                  xyxy[3].cpu().item())
                            p2 = (int(xyxy[0].cpu().item() + (xyxy[2].cpu().item() - xyxy[0].cpu().item()) / 3 * 2),
                                  xyxy[3].cpu().item())
                            pt = [p1, p2]
                            personinflag = mat.Path(person).contains_points(pt)
                            if personinflag.any():
                                # annotator.box_label(xyxy, None, color=(0, 0, 255))
                                # self.flag = True
                                if c == 0:
                                    dirp.setdefault(0, [])
                                    dirp[0].append(xyxy)
                                elif c in [1, 2]:
                                    dirp.setdefault(1, [])
                                    dirp[1].append(xyxy)
                                    dirf.setdefault(1, [])
                                    dirf[1].append(xyxy)
                                elif c == 3:
                                    dirp.setdefault(1, [])
                                    dirp[1].append(xyxy)
                                elif c == 4:
                                    dirf.setdefault(0, [])
                                    dirf[0].append(xyxy)
        if len(dirp.keys()) == 2:
            claimg = []
            clapoint = []
            for person in dirp[0]:
                for other in dirp[1]:
                    iou, newxyxy = compute_IOU(person, other)
                    if iou > 0.1:
                        print(newxyxy)
                        imgtmp = im0[int(newxyxy[1]):int(newxyxy[3]), int(newxyxy[0]):int(newxyxy[2])]
                        imgtmp = imgtmp[..., ::-1]
                        imgtmp = Image.fromarray(imgtmp)
                        imgten1 = test(imgtmp)
                        claimg.append(imgten1)
                        clapoint.append((newxyxy))
                        result = clapre(self.classifier_model, claimg, clapoint)
                        # imgten = imgten1[None]
                        # imgten = imgten.to(0)
                        # result = modelcla(imgten)
                        # result = F.softmax(result, dim=1)
                        # cla = result.argmax(1)
                        if result is not None:
                            self.flag = True
                            for res in result:
                                print(res)
                                annotator.box_label(res, None, color=(0, 0, 255))
        if len(dirp.keys()) == 2:
            claimg = []
            clapoint = []
            for person in dirp[0]:
                for other in dirp[1]:
                    iou, newxyxy = compute_IOU(person, other)
                    if iou > 0.1:
                        print(newxyxy)
                        imgtmp = im0[int(newxyxy[1]):int(newxyxy[3]), int(newxyxy[0]):int(newxyxy[2])]
                        imgtmp = imgtmp[..., ::-1]
                        imgtmp = Image.fromarray(imgtmp)
                        imgten1 = test(imgtmp)
                        claimg.append(imgten1)
                        clapoint.append((newxyxy))
                        result = clapre(self.classifier_model, claimg, clapoint)
                        # imgten = imgten1[None]
                        # imgten = imgten.to(0)
                        # result = modelcla(imgten)
                        # result = F.softmax(result, dim=1)
                        # cla = result.argmax(1)
                        if result is not None:
                            self.flag = True
                            for res in result:
                                print(res)
                                annotator.box_label(res, None, color=(0, 0, 255))
        return self.flag

class Persontree:
    def __init__(self):
        self.flag = False
        self.classifier_model = torch.load('/home/h3c/yolo/persontrecls.pt')
    def getflag(self, det, persondet, annotator, fence=0, point=None, names=None, rname=None, num=1, im0=None,
                channel=None):
        self.flag = False
        target_classes = [1, 2, 3]
        results = Results(annotator.result(), path=None, names=names, boxes=det)
        boxes = results.boxes
        person_boxes = []
        target_boxes = []
        cls4_boxes = []
        # 处理检测结果
        for i in range(len(boxes)):
            cls = int(boxes.cls[i].item())
            con = boxes.conf[i].item()
            if cls == 0 and con > 0.1:  # 如果是 "person" 类别
                x1, y1, x2, y2 = boxes.xyxy[i].tolist()
                person_boxes.append([x1, y1, x2, y2])
            if cls in target_classes and con > 0.1:  # 目标类别（bag, box, cart）
                x1, y1, x2, y2 = boxes.xyxy[i].tolist()
                target_boxes.append([x1, y1, x2, y2])
            if cls == 4 and con > 0.1:  # 如果是 "cls 4" 类别
                x1, y1, x2, y2 = boxes.xyxy[i].tolist()
                cls4_boxes.append([x1, y1, x2, y2])
        # 如果检测到 "person" 类别和目标框，计算IoU
        if person_boxes and target_boxes:
            for i, person_box in enumerate(person_boxes):
                person_center_y = (person_box[1] + person_box[3]) / 2
                for j, target_box in enumerate(target_boxes):
                    target_center_y = (target_box[1] + target_box[3]) / 2
                    # 判断目标框的中心点是否在person框的下方
                    if target_center_y + 20 > person_center_y:  # 根据需要调整此阈值
                        iou = calculate_iou(person_box, target_box)
                        if iou > 0:  # IoU大于0，进入新的判断
                            # 创建一个包围person和target框的区域 本来思路是判断脚是否在这个大框框里面 但是这个不合理 应该判断脚是不是在这个交集里面，再检测脚和人与物交集有没有交集
                            min_x = max(person_box[0], target_box[0])
                            min_y = max(person_box[1], target_box[1])
                            max_x = min(person_box[2], target_box[2])
                            max_y = min(person_box[3], target_box[3])
                            target_area = (min_x, min_y, max_x, max_y)
                            # 检查是否有cls 4物体在这个区域内
                            for cls4_box in cls4_boxes:  # 比较巧妙 提前存储这个变量 然后检测这个物体是不是在这里面
                                # 判断cls 4框是否与这个区域有交集
                                inter_x1 = max(cls4_box[0], target_area[0])
                                inter_y1 = max(cls4_box[1], target_area[1])
                                inter_x2 = min(cls4_box[2], target_area[2])
                                inter_y2 = min(cls4_box[3], target_area[3])
                                if inter_x1 < inter_x2 and inter_y1 < inter_y2:
                                    # 计算交集区域的面积
                                    intersection_area = (inter_x2 - inter_x1) * (inter_y2 - inter_y1)
                                    # 计算 cls4_box 的面积
                                    cls4_area = (cls4_box[2] - cls4_box[0]) * (cls4_box[3] - cls4_box[1])
                                    # 计算交集区域占 cls4_box 面积的比例
                                    overlap_ratio = intersection_area / cls4_area
                                    if overlap_ratio > 0.5:
                                        self.flag = True
        return self.flag

class Persontre:
    def __init__(self):
        self.flag = False
        self.classifier_model = torch.load('/home/h3c/yolo/persontrecls.pt')
    def getflag(self, det, persondet, annotator, fence=0, point=None, names=None, rname=None, num=1, im0=None,
                channel=None):
        self.flag = False
        cls3 = 3  # 对cart单独一类
        cls4 = 4  # 新增加的类别编号（假设为 4）
        target_classes = [1, 2, 3]
        results = Results(annotator.result(), path=None, names=names, boxes=det)
        boxes = results.boxes
        person_boxes = []  # 人 车子 脚 以及 指定区域内的脚
        cls3_boxes = []
        cls4_boxes = []
        best_cls4_box = []
        # 处理检测结果
        for i in range(len(boxes)):
            cls = int(boxes.cls[i].item())
            con = boxes.conf[i].item()
            if cls == 0 and con > 0.1:  # 如果是 "person" 类别  先把对应类别添加上去  先把每一个识别物体输入上去
                x1, y1, x2, y2 = boxes.xyxy[i].tolist()
                person_boxes.append([x1, y1, x2, y2])
            if cls == cls3 and con > 0.1:  # 目标类别 cart
                x1, y1, x2, y2 = boxes.xyxy[i].tolist()
                cls3_boxes.append([x1, y1, x2, y2])
            if cls == cls4 and con > 0.1:  # 如果是 "cls 4" 类别
                x1, y1, x2, y2 = boxes.xyxy[i].tolist()
                cls4_boxes.append([x1, y1, x2, y2])
        # 如果检测到 "person" 类别和目标框，计算IoU
        if person_boxes and cls3_boxes:  # 先查看这俩个类别有没有
            for i, person_box in enumerate(person_boxes):
                for j, cls3_box in enumerate(cls3_boxes):
                    # 判断目标框的中心点是否在person框的下方
                    iou = calculate_iou(person_box, cls3_box)
                    # 踩的逻辑 一个是要求车子和人有交并比 其次判断脚是不是在这个交并比内 并且比重不能太低
                    if iou > 0.2:  # 用来判断坐 如果iou足够高 就视为是坐
                        # 加载图像并绘制标注
                        # 看看这个值大概有多少 好衡量一下
                        # print(f"这个iou大于0.2的 这是第{frame_idx},iou是{iou}")  # 写入介绍
                        annotator.box_label(person_box, None, color=(0, 0, 255))
                        annotator.box_label(cls3_box, None, color=(0, 0, 255))
                        self.flag = True
                        # print("这是坐",f"{saved_image_path}")
                    elif iou > 0:  # IoU大于0，进入新的判断 代表不是坐
                        # 创建一个包围person和target框的区域 本来思路是判断脚是否在这个大框框里面 但是这个不合理 应该判断脚是不是在这个交集里面，再检测脚和人与物交集有没有交集
                        overlap_ratio, inter_xy, best_cls4_box1 = check_cls4_overlap(person_box, cls3_box, cls4_boxes)
                        best_cls4_box.extend(best_cls4_box1)  # 拿到这四个点的坐标
                        inter_x1, inter_y1 = inter_xy
                        # 如果占比大于某个阈值，可以执行进一步的操作
                        if overlap_ratio > 0.2:
                            annotator.box_label(person_box, None, color=(0, 0, 255))
                            annotator.box_label(cls3_box, None, color=(0, 0, 255))
                            annotator.box_label(best_cls4_box, None, color=(0, 0, 255))
                            self.flag = True

class Danager:
    def __init__(self):
        self.flag = False
    def getflag(self, det, persondet, annotator, fence=0, point=None, names=None, rname=None, num=1, channel=None):
        self.flag = False
        for *xyxy, conf, cls in reversed(det):
            c = int(cls)
            labelname = names[c]
            if labelname in rname:
                if fence == 1:
                    pointa = strtolstl(point)
                    for poi in pointa:
                        p1 = (int(xyxy[0].cpu().item() + (xyxy[2].cpu().item() - xyxy[0].cpu().item()) / 2),
                              int(xyxy[1].cpu().item() + (xyxy[3].cpu().item() - xyxy[1].cpu().item()) / 2))
                        # p2 = (int(xyxy[0].cpu().item() + (xyxy[2].cpu().item() - xyxy[0].cpu().item()) / 3 * 2),
                        # xyxy[3].cpu().item())
                        pt = [p1]
                        inflag = mat.Path(poi).contains_points(pt)
                        if inflag.any():
                            if persondet is None:
                                self.flag = True
                                # c = int(cls)  # integer class
                                # label = f'{self.names[c]} {conf:.2f}'
                                label = None
                                annotator.box_label(xyxy, None, color=(0, 0, 255))
                            else:
                                for person in persondet:
                                    personinflag = mat.Path(person).contains_points(pt)
                                    if personinflag.any():
                                        annotator.box_label(xyxy, None, color=(0, 0, 255))
                                        self.flag = True
                else:
                    if persondet is None:
                        self.flag = True
                        # c = int(cls)  # integer class
                        # label = f'{self.names[c]} {conf:.2f}'
                        label = None
                        annotator.box_label(xyxy, None, color=(0, 0, 255))
                    else:
                        for person in persondet:
                            p1 = (int(xyxy[0].cpu().item() + (xyxy[2].cpu().item() - xyxy[0].cpu().item()) / 3),
                                  xyxy[3].cpu().item())
                            p2 = (int(xyxy[0].cpu().item() + (xyxy[2].cpu().item() - xyxy[0].cpu().item()) / 3 * 2),
                                  xyxy[3].cpu().item())
                            pt = [p1, p2]
                            personinflag = mat.Path(person).contains_points(pt)
                            if personinflag.any():
                                annotator.box_label(xyxy, None, color=(0, 0, 255))
                                self.flag = True
        return self.flag

class Clear:
    def __init__(self):
        self.flag = False
    def getflag(self, det, persondet, annotator, fence=0, point=None, names=None, rname=None, num=1, channel=None):
        self.flag = False
        for *xyxy, conf, cls in reversed(det):
            c = int(cls)
            labelname = names[c]
            if labelname in rname:
                if fence == 1:
                    pointa = strtolstl(point)
                    for poi in pointa:
                        p1 = (int(xyxy[0].cpu().item() + (xyxy[2].cpu().item() - xyxy[0].cpu().item()) / 2),
                              int(xyxy[1].cpu().item() + (xyxy[3].cpu().item() - xyxy[1].cpu().item()) / 2))
                        # p2 = (int(xyxy[0].cpu().item() + (xyxy[2].cpu().item() - xyxy[0].cpu().item()) / 3 * 2),
                        # xyxy[3].cpu().item())
                        pt = [p1]
                        inflag = mat.Path(poi).contains_points(pt)
                        if inflag.any():
                            if persondet is None:
                                self.flag = True
                                print('hand')
                                # c = int(cls)  # integer class
                                # label = f'{self.names[c]} {conf:.2f}'
                                label = None
                                annotator.box_label(xyxy, None, color=(0, 0, 255))
                            else:
                                for person in persondet:
                                    personinflag = mat.Path(person).contains_points(pt)
                                    if personinflag.any():
                                        annotator.box_label(xyxy, None, color=(0, 0, 255))
                                        self.flag = True
                else:
                    if persondet is None:
                        self.flag = True
                        # c = int(cls)  # integer class
                        # label = f'{self.names[c]} {conf:.2f}'
                        label = None
                        annotator.box_label(xyxy, None, color=(0, 0, 255))
                    else:
                        for person in persondet:
                            p1 = (int(xyxy[0].cpu().item() + (xyxy[2].cpu().item() - xyxy[0].cpu().item()) / 3),
                                  xyxy[3].cpu().item())
                            p2 = (int(xyxy[0].cpu().item() + (xyxy[2].cpu().item() - xyxy[0].cpu().item()) / 3 * 2),
                                  xyxy[3].cpu().item())
                            pt = [p1, p2]
                            personinflag = mat.Path(person).contains_points(pt)
                            if personinflag.any():
                                annotator.box_label(xyxy, None, color=(0, 0, 255))
                                self.flag = True
        return self.flag

class newPersontre:
    def __init__(self):
        self.flag = False
        self.classifier_model = torch.load('/home/h3c/yolo/persontrecls.pt')
    def getflag(self, det, persondet, annotator, fence=0, point=None, names=None, rname=None, num=1, im0=None,
                channel=None):
        self.flag = False
        cls3 = 1  # 对cart单独一类
        # cls4 = 4  # 新增加的类别编号（假设为 4）
        # target_classes = [1, 2, 3]
        height, width, _ = annotator.result().shape
        right_threshold = width * 0.9
        results = Results(annotator.result(), path=None, names=names, boxes=det)
        boxes = results.boxes
        print(boxes)
        person_boxes = []  # 人 车子 脚 以及 指定区域内的脚
        cls3_boxes = []
        # cls4_boxes = []
        # best_cls4_box = []
        # 处理检测结果
        for i in range(len(boxes)):
            perflag = False
            cls = int(boxes.cls[i].item())
            con = boxes.conf[i].item()
            if cls == 0 and con > 0.5:  # 如果是 "person" 类别  先把对应类别添加上去  先把每一个识别物体输入上去
                x1, y1, x2, y2 = boxes.xyxy[i].tolist()
                for personbox in persondet:
                    iou = calculate_iou(boxes.xyxy[i].tolist(),
                                        [personbox[0], personbox[1], personbox[4], personbox[5]])
                    if iou > 0.8:
                        perflag = True
                        break
                if perflag:
                    person_boxes.append([x1, y1, x2, y2])
            # if cls == cls3 and con > 0.1:  # 目标类别 cart
            #    x1, y1, x2, y2 = boxes.xyxy[i].tolist()
            #    cls3_boxes.append([x1, y1, x2, y2])
        # 如果检测到 "person" 类别和目标框，计算IoU
        if person_boxes:  # 先查看这俩个类别有没有
            for i, person_box in enumerate(person_boxes):
                # for j, cls3_box in enumerate(cls3_boxes):
                # 判断是否存在交集 而且不能低
                # iou = calculate_iou(person_box, cls3_box)
                # print(f"IOU的大小这是第,iou")
                # 新增宽高比判断
                # cart_width = cls3_box[2] - cls3_box[0]
                # cart_height = cls3_box[3] - cls3_box[1]
                # if cart_width > cart_height and iou > 0.15:
                # if iou > 0.15:
                # 原有绘图保存代码保持不变
                # print(f"这个iou大于0.2的 这是第,iou是{iou}")
                # img = Image.fromarray(cv2.cvtColor(frame,
                # cv2.COLOR_BGR2RGB))
                # draw = ImageDraw.Draw(img)
                # 绘制矩形框
                # draw.rectangle([person_box[0], person_box[1], person_box[2], person_box[3]],
                #                outline="red", width=3)
                # draw.rectangle([cls3_box[0], cls3_box[1], cls3_box[2], cls3_box[3]],
                #                outline="blue", width=3)
                # saved_image_path = os.path.join(output_dir1,
                #                                f"{timestamp}_{frame_idx}_detected.jpg")
                # img.save(saved_image_path)
                # print(f"这是坐，已保存")
                a_center = (personbox[0] + personbox[2]) / 2
                if a_center >= right_threshold:
                    continue
                annotator.box_label(person_box, None, color=(0, 0, 255))
                # annotator.box_label(cls3_box, None, color=(0, 0, 255))
                self.flag = True
        return self.flag

class CarHelmetBelt:
    def __init__(self):
        self.flag = False
    def selectNoBeltPerson(self, person_objs, belt_objs):
        objs = []
        polygon_person = [Polygon(
            [(left, top), (right, top), (right, bottom), (left, bottom)]) for left, top, right, bottom, _, _ in
            person_objs]
        polygon_belt = [Polygon(
            [(left, top), (right, top), (right, bottom), (left, bottom)]) for left, top, right, bottom, _, _ in
            belt_objs]
        for person_obj, person in zip(person_objs, polygon_person):
            with_belt = False
            for belt in polygon_belt:
                if person.intersection(belt).area / belt.area > 0.5:
                    with_belt = True
                    break
            if not with_belt:
                objs.append(person_obj)
        return objs
    def selectWithPersonHead(self, person_objs, head_objs):
        objs = []
        polygon_person = [Polygon(
            [(left, top), (right, top), (right, top + (bottom - top) / 2), (left, top + (bottom - top) / 2)]) for
            left, top, right, bottom, _, _ in person_objs]
        polygon_head = [Polygon(
            [(left, top), (right, top), (right, bottom), (left, bottom)]) for left, top, right, bottom, _, _ in
            head_objs]
        for head_obj, head in zip(head_objs, polygon_head):
            with_person = False
            for person in polygon_person:
                print('head')
                if person.intersection(head).area / head.area > 0.5:
                    with_person = True
                    break
            if with_person:
                objs.append(head_obj)
        return objs
    def getflag(self, det, persondet, annotator, fence=0, point=None, names=None, rname=None, num=1, channel=None):
        self.flag = False
        results = Results(annotator.result(), path=None, names=names, boxes=det)
        person_objs = []
        # if persondet:
        #    for person in persondet:
        #        person_objs.append([person[0],person[1],person[4],person[5],'_','_'])
        head_objs = []
        belt_objs = []
        self.polygon_areas = [Polygon(strtolstl(point)[0])]
        if self.polygon_areas is not None:
            for person in persondet:
                polygon_box = Polygon(
                    [(person[0], person[1]), (person[2], person[3]), (person[4], person[5]), (person[6], person[7])])
                intersection_areas = [polygon_area.intersection(polygon_box).area for polygon_area in
                                      self.polygon_areas]
                if sum(intersection_areas) == 0:
                    continue
                intersection_areas_ratio = sorted(
                    [intersection_area / polygon_box.area for intersection_area in intersection_areas])
                # print(intersection_areas_ratio)
                if intersection_areas_ratio[-1] < 0.3:
                    continue
                person_objs.append([person[0], person[1], person[4], person[5], '_', '_'])
            # persondet = tmppersondet
        for result in results:
            boxes = result.boxes
            for box in boxes:
                # print(box.conf.cpu())
                left, top, right, bottom = box.xyxy.cpu().numpy().tolist()[0]
                polygon_box = Polygon([(left, top), (right, top), (right, bottom), (left, bottom)])
                intersection_areas = [polygon_area.intersection(polygon_box).area for polygon_area in
                                      self.polygon_areas]
                if sum(intersection_areas) == 0:
                    continue
                intersection_areas_ratio = sorted(
                    [intersection_area / polygon_box.area for intersection_area in intersection_areas])
                if intersection_areas_ratio[-1] < 0.9:
                    continue
                conf = box.conf.cpu().numpy().tolist()[0]
                cls = box.cls.cpu().numpy().tolist()[0]
                # if cls == 0 and conf>0.8:
                #    person_objs.append([left, top, right, bottom, conf, names[cls]])
                if cls == 1:
                    head_objs.append([left, top, right, bottom, conf, names[cls]])
                elif cls == 3:
                    belt_objs.append([left, top, right, bottom, conf, names[cls]])
                # print(head_objs)
                # print(person_objs)
        illegal_objs = self.selectNoBeltPerson(person_objs, belt_objs) + self.selectWithPersonHead(person_objs,
                                                                                                   head_objs)
        if len(illegal_objs) > 0:
            for obj in illegal_objs:
                annotator.box_label(obj[:4], None, color=(0, 0, 255))
            self.flag = True
        return self.flag

class newUniformi1:
    def __init__(self):
        self.flag = False
    def selectNoUniformPerson(self, person_objs, uniform_objs):
        objs = []
        print(person_objs)
        print(uniform_objs)
        polygon_person = [Polygon(
            [(left, top), (right, top), (right, bottom), (left, bottom)]) for left, top, right, bottom, _, _ in
            person_objs]
        polygon_uniform = [Polygon(
            [(left, top), (right, top), (right, bottom), (left, bottom)]) for left, top, right, bottom, _, _ in
            uniform_objs]
        for person_obj, person in zip(person_objs, polygon_person):
            with_uniform = False
            for uniform in polygon_uniform:
                if person.intersection(uniform).area / uniform.area > 0.3:
                    with_uniform = True
                    break
            if not with_uniform:
                print(f'illperson_obj {person_obj} illpolygon_uniform {polygon_uniform}')
                objs.append(person_obj)
        return objs
    def getflag(self, det, persondet, annotator, fence=0, point=None, names=None, rname=None, num=1, channel=None):
        self.flag = False
        results = Results(annotator.result(), path=None, names=names, boxes=det)
        print(results.boxes)
        person_objs = []
        uniform_objs = []
        # belt_objs = []
        if len(point) > 1:
            self.polygon_areas = [Polygon(strtolstl(point)[0])]
        else:
            self.polygon_areas = None
        if persondet is not None:
            if self.polygon_areas is not None:
                for left, top, right, top, right, bottom, left, bottom in persondet:
                    polygon_box = Polygon([(left, top), (right, top), (right, bottom), (left, bottom)])
                    intersection_areas = [polygon_area.intersection(polygon_box).area for polygon_area in
                                          self.polygon_areas]
                    if sum(intersection_areas) == 0:
                        continue
                    intersection_areas_ratio = sorted(
                        [intersection_area / polygon_box.area for intersection_area in intersection_areas])
                    print(f'inter = {intersection_areas_ratio}')
                    if intersection_areas_ratio[-1] >= 0.3:
                        print("person in check space!!!")
                        width = right - left
                        height = bottom - top
                        print(f'{left}, {top}, {right},{top},{right}, {bottom},{left},{bottom}')
                        print(f'hw = {width * height}')
                        if width * height > 10000:
                            person_objs.append([left, top, right, bottom, 0.25, 'person'])
        for result in results:
            boxes = result.boxes
            for box in boxes:
                left, top, right, bottom = box.xyxy.cpu().numpy().tolist()[0]
                # if self.polygon_areas is not None :
                #     if persondet is None and box.cls.cpu().numpy().tolist()[0] == 4:
                #         polygon_box = Polygon([(left, top), (right, top), (right, bottom), (left, bottom)])
                #
                #         intersection_areas = [polygon_area.intersection(polygon_box).area for polygon_area in self.polygon_areas ]
                #         if sum(intersection_areas) == 0:
                #             continue
                #
                #         intersection_areas_ratio = sorted([intersection_area / polygon_box.area for intersection_area in intersection_areas])
                #         print(f'inter = {intersection_areas_ratio}')
                #         if intersection_areas_ratio[-1] < 0.3:
                #             continue
                conf = box.conf.cpu().numpy().tolist()[0]
                cls = box.cls.cpu().numpy().tolist()[0]
                # if persondet is not None:
                #     if cls == 4 and conf >=0.7:
                #         width = right - left
                #         height = bottom - top
                #         if width * height >10000:
                #             person_objs.append([left, top, right, bottom, conf, names[cls]])
                if cls in [1, 2]:
                    # width = right - left
                    # height = bottom - top
                    # if width * height >4096:
                    uniform_objs.append([left, top, right, bottom, conf, names[cls]])
        print(f'personobjs = {person_objs}')
        print(f'uniformobjs = {uniform_objs}')
        illegal_objs = self.selectNoUniformPerson(person_objs, uniform_objs)
        if len(illegal_objs) > 0:
            for obj in illegal_objs:
                annotator.box_label(obj[:4], None, color=(0, 0, 255))
            self.flag = True
        return self.flag

class newHelmet:
    def __init__(self):
        self.flag = False
    def selectNoHelmetPerson(self, person_objs, head_objs):
        objs = []
        polygon_person = [Polygon(
            [(left, top), (right, top), (right, bottom), (left, bottom)]) for left, top, right, bottom, _, _ in
            person_objs]
        polygon_head = [Polygon(
            [(left, top), (right, top), (right, bottom), (left, bottom)]) for left, top, right, bottom, _, _ in
            head_objs]
        for person_obj, person in zip(person_objs, polygon_person):
            with_head = False
            for head in polygon_head:
                print('head')
                if person.intersection(head).area / head.area > 0.7:
                    with_head = True
                    break
            if with_head:
                objs.append(person_obj)
        # for head in polygon_head:
        #    with_head = False
        #    for person_obj, person in zip(person_objs, polygon_person):
        #        print('head')
        #        if person.intersection(head).area / head.area > 0.7:
        #            with_head = True
        #            break
        #    if  with_head:
        #        objs.append(person_obj)
        return objs
    def getflag(self, det, persondet, annotator, fence=0, point=None, names=None, rname=None, num=1, channel=None):
        self.flag = False
        results = Results(annotator.result(), path=None, names=names, boxes=det)
        person_objs = []
        head_objs = []
        helmet_objs = []
        headtmp = []
        # belt_objs = []
        if len(point) > 1:
            self.polygon_areas = [Polygon(strtolstl(point)[0])]
        else:
            self.polygon_areas = None
        for result in results:
            boxes = result.boxes
            for box in boxes:
                left, top, right, bottom = box.xyxy.cpu().numpy().tolist()[0]
                if self.polygon_areas is not None:
                    polygon_box = Polygon([(left, top), (right, top), (right, bottom), (left, bottom)])
                    intersection_areas = [polygon_area.intersection(polygon_box).area for polygon_area in
                                          self.polygon_areas]
                    if sum(intersection_areas) == 0:
                        continue
                    intersection_areas_ratio = sorted(
                        [intersection_area / polygon_box.area for intersection_area in intersection_areas])
                    if intersection_areas_ratio[-1] < 0.9:
                        continue
                conf = box.conf.cpu().numpy().tolist()[0]
                cls = box.cls.cpu().numpy().tolist()[0]
                # print(f'{conf} {cls}')
                # print(cls in [5,6,7,8,9,10])
                if cls == 4 and conf >= 0.7:
                    width = right - left
                    height = bottom - top
                    if channel == 32:
                        whflag = width * height > 2048
                    else:
                        whflag = width * height > 4096
                    if whflag:
                        person_objs.append([left, top, right, bottom, conf, names[cls]])
                elif cls == 0 and conf >= 0.5:
                    # width = right - left
                    # height = bottom - top
                    # if width * height >4096:
                    print('------')
                    headtmp.append([left, top, right, bottom, conf, names[cls]])
                elif cls in [5, 6, 7, 8, 9, 10]:
                    helmet_objs.append([(left, top), (right, top), (right, bottom), (left, bottom)])
        print(f'headtmp= {headtmp}')
        print(f'helmet_objs = {helmet_objs}')
        for left, top, right, bottom, conf, name in headtmp:
            flag = False
            pt = [(int((left + right) / 2), int((top + bottom) / 2))]
            for helmet in helmet_objs:
                pflag = mat.Path(helmet).contains_points(pt)
                if pflag.any():
                    flag = True
                    break
            if not flag:
                head_objs.append([left, top, right, bottom, conf, name])
        # print(f'person_objs = {person_objs}')
        illegal_objs = self.selectNoHelmetPerson(person_objs, head_objs)
        # print(f'illegal_objs = {illegal_objs}')
        if len(illegal_objs) > 0:
            for obj in illegal_objs:
                annotator.box_label(obj[:4], None, color=(0, 0, 255))
            self.flag = True
        # import cv2
        # cv2.imwrite("helmet.jpg",annotator.result())
        return self.flag

class newHelmetn:
    def __init__(self):
        self.flag = False
    def selectNoHelmetPerson(self, person_objs, head_objs):
        objs = []
        polygon_person = [Polygon(
            [(left, top), (right, top), (right, bottom), (left, bottom)]) for left, top, right, bottom, _, _ in
            person_objs]
        polygon_head = [Polygon(
            [(left, top), (right, top), (right, bottom), (left, bottom)]) for left, top, right, bottom, _, _ in
            head_objs]
        for person_obj, person in zip(person_objs, polygon_person):
            with_head = False
            for head in polygon_head:
                if person.intersection(head).area / head.area > 0.3:
                    with_head = True
                    break
            if with_head:
                objs.append(person_obj)
        return objs
    def getflag(self, det, persondet, annotator, fence=0, point=None, names=None, rname=None, num=1, channel=None):
        self.flag = False
        results = Results(annotator.result(), path=None, names=names, boxes=det)
        person_objs = []
        head_objs = []
        # belt_objs = []
        if len(point) > 1:
            self.polygon_areas = [Polygon(strtolstl(point)[0])]
        else:
            self.polygon_areas = None
        for result in results:
            boxes = result.boxes
            for box in boxes:
                left, top, right, bottom = box.xyxy.cpu().numpy().tolist()[0]
                if self.polygon_areas is not None:
                    polygon_box = Polygon([(left, top), (right, top), (right, bottom), (left, bottom)])
                    intersection_areas = [polygon_area.intersection(polygon_box).area for polygon_area in
                                          self.polygon_areas]
                    if sum(intersection_areas) == 0:
                        continue
                    intersection_areas_ratio = sorted(
                        [intersection_area / polygon_box.area for intersection_area in intersection_areas])
                    if intersection_areas_ratio[-1] < 0.9:
                        continue
                conf = box.conf.cpu().numpy().tolist()[0]
                cls = box.cls.cpu().numpy().tolist()[0]
                if cls == 4:
                    width = right - left
                    height = bottom - top
                    if width * height > 4096:
                        person_objs.append([left, top, right, bottom, conf, names[cls]])
                elif cls == 0:
                    # width = right - left
                    # height = bottom - top
                    # if width * height >4096:
                    head_objs.append([left, top, right, bottom, conf, names[cls]])
        illegal_objs = self.selectNoHelmetPerson(person_objs, head_objs)
        if len(illegal_objs) > 0:
            for obj in illegal_objs:
                annotator.box_label(obj[:4], None, color=(0, 0, 255))
            self.flag = True
        return self.flag

class newUniformt:
    def __init__(self):
        self.flag = False
    def selectNoUniformPerson(self, person_objs, uniform_objs):
        objs = []
        print(person_objs)
        print(uniform_objs)
        polygon_person = [Polygon(
            [(left, top), (right, top), (right, bottom), (left, bottom)]) for left, top, right, bottom, _, _ in
            person_objs]
        polygon_uniform = [Polygon(
            [(left, top), (right, top), (right, bottom), (left, bottom)]) for left, top, right, bottom, _, _ in
            uniform_objs]
        for person_obj, person in zip(person_objs, polygon_person):
            with_uniform = False
            for uniform in polygon_uniform:
                if person.intersection(uniform).area / uniform.area > 0.3:
                    with_uniform = True
                    break
            if not with_uniform:
                print(f'illperson_obj {person_obj} illpolygon_uniform {polygon_uniform}')
                objs.append(person_obj)
        return objs
    def selectHeadPerson(self, person_objs, head_objs):
        objs = []
        print(person_objs)
        print(head_objs)
        # personlist = []
        polygon_person = [Polygon(
            [(left, top), (right, top), (right, bottom), (left, bottom)]) for left, top, right, bottom, _, _ in
            person_objs]
        polygon_head = [Polygon(
            [(left, top), (right, top), (right, bottom), (left, bottom)]) for left, top, right, bottom, _, _ in
            uniform_objs]
        for person_obj, person in zip(person_objs, polygon_person):
            # with_uniform = False
            for head in polygon_head:
                if person.intersection(head).area / head.area > 0.3:
                    # with_uniform = True
                    # break
                    # if not with_uniform:
                    #    print(f'illperson_obj {person_obj} illpolygon_uniform {polygon_uniform}')
                    objs.append(person_obj)
                    break
        return objs
    def getflag(self, det, persondet, annotator, fence=0, point=None, names=None, rname=None, num=1, channel=None):
        self.flag = False
        results = Results(annotator.result(), path=None, names=names, boxes=det)
        print(results.boxes)
        person_objs = []
        uniform_objs = []
        head_objs = []
        # belt_objs = []
        if len(point) > 1:
            self.polygon_areas = [Polygon(strtolstl(point)[0])]
        else:
            self.polygon_areas = None
        for result in results:
            boxes = result.boxes
            for box in boxes:
                left, top, right, bottom = box.xyxy.cpu().numpy().tolist()[0]
                if self.polygon_areas is not None:
                    polygon_box = Polygon([(left, top), (right, top), (right, bottom), (left, bottom)])
                    intersection_areas = [polygon_area.intersection(polygon_box).area for polygon_area in
                                          self.polygon_areas]
                    if sum(intersection_areas) == 0:
                        continue
                    intersection_areas_ratio = sorted(
                        [intersection_area / polygon_box.area for intersection_area in intersection_areas])
                    if intersection_areas_ratio[-1] < 0.9:
                        continue
                conf = box.conf.cpu().numpy().tolist()[0]
                cls = box.cls.cpu().numpy().tolist()[0]
                if cls == 4:
                    width = right - left
                    height = bottom - top
                    if width * height > 4096:
                        person_objs.append([left, top, right, bottom, conf, names[cls]])
                elif cls in [1, 2]:
                    # width = right - left
                    # height = bottom - top
                    # if width * height >4096:
                    uniform_objs.append([left, top, right, bottom, conf, names[cls]])
                elif cls != 3:
                    head_objs.append([left, top, right, bottom, conf, names[cls]])
        person_objs = self.selectNoUniformPerson(person_objs, head_objs)
        illegal_objs = self.selectNoUniformPerson(person_objs, uniform_objs)
        if len(illegal_objs) > 0:
            for obj in illegal_objs:
                annotator.box_label(obj[:4], None, color=(0, 0, 255))
            self.flag = True
        return self.flag

class newUniform:
    def __init__(self):
        self.flag = False
    def selectNoUniformPerson(self, person_objs, uniform_objs):
        objs = []
        print(person_objs)
        print(uniform_objs)
        polygon_person = [Polygon(
            [(left, top), (right, top), (right, bottom), (left, bottom)]) for left, top, right, bottom, _, _ in
            person_objs]
        polygon_uniform = [Polygon(
            [(left, top), (right, top), (right, bottom), (left, bottom)]) for left, top, right, bottom, _, _ in
            uniform_objs]
        for person_obj, person in zip(person_objs, polygon_person):
            with_uniform = False
            for uniform in polygon_uniform:
                if person.intersection(uniform).area / uniform.area > 0.3:
                    with_uniform = True
                    break
            if not with_uniform:
                print(f'illperson_obj {person_obj} illpolygon_uniform {polygon_uniform}')
                objs.append(person_obj)
        return objs
    def getflag(self, det, persondet, annotator, fence=0, point=None, names=None, rname=None, num=1, channel=None):
        self.flag = False
        results = Results(annotator.result(), path=None, names=names, boxes=det)
        print(results.boxes)
        person_objs = []
        uniform_objs = []
        print(f'persondet = {persondet}')
        # belt_objs = []
        if len(point) > 1:
            self.polygon_areas = [Polygon(strtolstl(point)[0])]
            print(self.polygon_areas)
        else:
            self.polygon_areas = None
        tmppersondet = []
        if self.polygon_areas is not None:
            for person in persondet:
                polygon_box = Polygon(
                    [(person[0], person[1]), (person[2], person[3]), (person[4], person[5]), (person[6], person[7])])
                intersection_areas = [polygon_area.intersection(polygon_box).area for polygon_area in
                                      self.polygon_areas]
                if sum(intersection_areas) == 0:
                    continue
                intersection_areas_ratio = sorted(
                    [intersection_area / polygon_box.area for intersection_area in intersection_areas])
                # print(intersection_areas_ratio)
                if intersection_areas_ratio[-1] < 0.3:
                    continue
                tmppersondet.append(person)
            persondet = tmppersondet
        print(f'tmppersondet = {tmppersondet}')
        # persondet = tmppersondet
        for result in results:
            boxes = result.boxes
            for box in boxes:
                left, top, right, bottom = box.xyxy.cpu().numpy().tolist()[0]
                conf = box.conf.cpu().numpy().tolist()[0]
                cls = box.cls.cpu().numpy().tolist()[0]
                # if self.polygon_areas is not None and cls == 4:
                #    polygon_box = Polygon([(left, top), (right, top), (right, bottom), (left, bottom)])
                #     intersection_areas = [polygon_area.intersection(polygon_box).area for polygon_area in self.polygon_areas ]
                #     if sum(intersection_areas) == 0:
                #         continue
                #     intersection_areas_ratio = sorted([intersection_area / polygon_box.area for intersection_area in intersection_areas])
                #     if intersection_areas_ratio[-1] < 0.9:
                #         continue
                # conf = box.conf.cpu().numpy().tolist()[0]
                # cls = box.cls.cpu().numpy().tolist()[0]
                print(conf)
                print(cls)
                if cls == 4 and conf >= 0.85:
                    width = right - left
                    height = bottom - top
                    print(width * height)
                    if channel == 32:
                        whflag = width * height > 5000
                    else:
                        whflag = width * height > 10000
                    if whflag:
                        for person in persondet:
                            # p1 = (int(xyxy[0].cpu().item() + (xyxy[2].cpu().item() - xyxy[0].cpu().item()) / 3),
                            # xyxy[3].cpu().item())
                            # p2 = (int(xyxy[0].cpu().item() + (xyxy[2].cpu().item() - xyxy[0].cpu().item()) / 3 * 2),
                            #      xyxy[3].cpu().item())
                            personcenterx = int((person[0] + person[2]) / 2)
                            personcentery = int((person[1] + person[7]) / 2)
                            p1 = (personcenterx, personcentery)
                            print(p1)
                            pt = [p1]
                            print(f'p1 = {p1}')
                            print(f'person = {person}')
                            personinflag = mat.Path(
                                [(left, top), (right, top), (right, bottom), (left, bottom)]).contains_points(pt)
                            if personinflag.any():
                                person_objs.append([left, top, right, bottom, conf, names[cls]])
                elif cls in [1, 2]:
                    # width = right - left
                    # height = bottom - top
                    # if width * height >4096:
                    uniform_objs.append([left, top, right, bottom, conf, names[cls]])
        illegal_objs = self.selectNoUniformPerson(person_objs, uniform_objs)
        if len(illegal_objs) > 0:
            for obj in illegal_objs:
                annotator.box_label(obj[:4], None, color=(0, 0, 255))
            self.flag = True
        return self.flag