Category: Mouse Events

本文详细介绍了JavaScript中与鼠标操作相关的事件处理方式,包括点击(click)、双击(dblclick)、悬停(hover)等常见事件的绑定及触发机制。通过这些事件,开发者可以为用户提供更加丰富的交互体验。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

.click()

Bind an event handler to the “click” JavaScript event, or trigger that event on an element.

.dblclick()

Bind an event handler to the “dblclick” JavaScript event, or trigger that event on an element.

.hover()

Bind one or two handlers to the matched elements, to be executed when the mouse pointer enters and leaves the elements.

.mousedown()

Bind an event handler to the “mousedown” JavaScript event, or trigger that event on an element.

.mouseenter()

Bind an event handler to be fired when the mouse enters an element, or trigger that handler on an element.

.mouseleave()

Bind an event handler to be fired when the mouse leaves an element, or trigger that handler on an element.

.mousemove()

Bind an event handler to the “mousemove” JavaScript event, or trigger that event on an element.

.mouseout()

Bind an event handler to the “mouseout” JavaScript event, or trigger that event on an element.

.mouseover()

Bind an event handler to the “mouseover” JavaScript event, or trigger that event on an element.

.mouseup()

Bind an event handler to the “mouseup” JavaScript event, or trigger that event on an element.

Also in: Deprecated > Deprecated 1.8 | Removed

.toggle()

Bind two or more handlers to the matched elements, to be executed on alternate clicks.






      本文转自Ansue  51CTO博客,原文链接:http://blog.51cto.com/ansue/1632340,如需转载请自行联系原作者


# -*- coding: utf-8 -*- """ Traffic Monitoring System v2.5 (Camera Version) Features: - Real-time camera object detection - YOLOv8 object detection - ByteTrack tracking - Matching colors for boxes and trajectories - Huawei Cloud IoT data reporting - Movable table - Trajectory display """ import os import sys import cv2 import numpy as np import torch import supervision as sv from ultralytics import YOLO from typing import Dict, Optional, Tuple, List import warnings import time import logging import socket import json from pathlib import Path from collections import defaultdict, deque # Import Huawei IoT SDK with encoding handling try: from iot_device_sdk_python.client.client_conf import ClientConf from iot_device_sdk_python.client.connect_auth_info import ConnectAuthInfo from iot_device_sdk_python.iot_device import IotDevice from iot_device_sdk_python.client.request.service_property import ServiceProperty except ImportError as e: logging.error(f"Huawei IoT SDK import error: {str(e)}") sys.exit(1) # Configure global logging with UTF-8 encoding logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', handlers=[ logging.StreamHandler(), logging.FileHandler('traffic_monitor.log', encoding='utf-8', mode='a') ] ) logger = logging.getLogger("TrafficMonitor") class Config: """System configuration parameters""" MODEL_PATH = r"C:\Users\yuanb\Desktop\物联网设计大赛无pyqt同时MQTT传输\runs\detect\train_v8\weights\best.pt" CLASS_NAMES = { 0: 'Pedestrian', 1: 'Person', 2: 'Bicycle', 3: 'Car', 4: 'Van', 5: 'Truck', 6: 'Tricycle', 7: 'CoveredTricycle', 8: 'Bus', 9: 'Motorcycle' } # Color palette for different classes CLASS_COLORS = { 0: (255, 0, 0), # Red - Pedestrian 1: (0, 255, 0), # Green - Person 2: (0, 0, 255), # Blue - Bicycle 3: (255, 255, 0), # Yellow - Car 4: (255, 0, 255), # Magenta - Van 5: (0, 255, 255), # Cyan - Truck 6: (255, 128, 0), # Orange - Tricycle 7: (128, 0, 255), # Purple - CoveredTricycle 8: (0, 128, 255), # Light Blue - Bus 9: (255, 0, 128) # Pink - Motorcycle } IOT_CONFIG = { "server_uri": "117.78.5.125", "port": 1883, "device_id": "681eeebc9314d118511a5690_DEV4", "secret": "Wjy15640916538", "service_id": "鲁班猫4", "use_tls": False, "keep_alive": 300, "clean_session": False } REPORT_INTERVAL = 10 MIN_REPORT_INTERVAL = 30 LINE_COLOR = sv.Color(r=0, g=255, b=0) TEXT_COLOR = (255, 255, 255) # White text for better visibility FONT_SCALE = 0.7 TABLE_POSITION = (10, 400) # Initial position, will be updated by mouse TABLE_ROW_HEIGHT = 30 TABLE_COL_WIDTH = 180 # Increased width TABLE_COLORS = { 'header': (0, 100, 255), 'row_even': (50, 50, 50), 'row_odd': (80, 80, 80), 'text': (255, 255, 255) } TRACK_HISTORY_LENGTH = 30 # Number of trajectory points to keep class LineCounter: """Improved counting logic with bidirectional counting and classification""" def __init__(self, start_point: sv.Point, end_point: sv.Point): self.start = start_point self.end = end_point self.tracker_state = {} self.counts = { 'Inbound_Vehicle': 0, 'Outbound_Vehicle': 0, 'Inbound_Pedestrian': 0, 'Outbound_Pedestrian': 0, 'Total_Vehicles': 0, 'Total_Pedestrians': 0 } self.class_mapping = { 'Vehicle': {3, 4, 5, 6, 7, 8, 9}, 'Pedestrian': {0, 1} } self.history = [] def _get_side(self, point: sv.Point) -> bool: """Calculate which side of the line the point is on (cross product method)""" vector_line = (self.end.x - self.start.x, self.end.y - self.start.y) vector_point = (point.x - self.start.x, point.y - self.start.y) cross_product = vector_line[0] * vector_point[1] - vector_line[1] * vector_point[0] return cross_product > 0 def update(self, detections: sv.Detections): """Update counter state""" current_counts = { 'Inbound_Vehicle': 0, 'Outbound_Vehicle': 0, 'Inbound_Pedestrian': 0, 'Outbound_Pedestrian': 0, } for xyxy, _, confidence, class_id, tracker_id in detections: if tracker_id is None or confidence < 0.5: continue # Calculate center point x1, y1, x2, y2 = xyxy center = sv.Point(x=int((x1 + x2) / 2), y=int((y1 + y2) / 2)) current_side = self._get_side(center) # Initialize new object if tracker_id not in self.tracker_state: self.tracker_state[tracker_id] = current_side continue # Check if crossed the line if self.tracker_state[tracker_id] != current_side: if class_id in self.class_mapping['Vehicle']: direction = 'Inbound' if current_side else 'Outbound' current_counts[f'{direction}_Vehicle'] += 1 self.counts[f'{direction}_Vehicle'] += 1 self.counts['Total_Vehicles'] += 1 elif class_id in self.class_mapping['Pedestrian']: direction = 'Inbound' if current_side else 'Outbound' current_counts[f'{direction}_Pedestrian'] += 1 self.counts[f'{direction}_Pedestrian'] += 1 self.counts['Total_Pedestrians'] += 1 self.tracker_state[tracker_id] = current_side if any(current_counts.values()): self.history.append({ 'timestamp': time.time(), 'counts': current_counts.copy() }) def get_counts(self) -> Dict[str, int]: """Get current statistics""" return self.counts.copy() def get_recent_counts(self, seconds=10) -> Dict[str, int]: """Get counts from recent specified time period""" recent_counts = { 'Inbound_Vehicle': 0, 'Outbound_Vehicle': 0, 'Inbound_Pedestrian': 0, 'Outbound_Pedestrian': 0 } cutoff = time.time() - seconds for record in reversed(self.history): if record['timestamp'] < cutoff: break for key in recent_counts: recent_counts[key] += record['counts'].get(key, 0) return recent_counts class HuaweiIoTClient: """Huawei Cloud IoT Client""" def __init__(self, config: dict): self.config = config self.device = None self.max_retries = 5 self.base_reconnect_delay = 5 self.last_report_time = 0 self._initialize_client() def _initialize_client(self): """Initialize client connection""" try: auth_info = ConnectAuthInfo() auth_info.server_uri = self.config["server_uri"] auth_info.port = self.config["port"] auth_info.id = self.config["device_id"] auth_info.secret = self.config["secret"] self.config["use_tls"] = False client_conf = ClientConf(auth_info) client_conf.clean_session = self.config["clean_session"] client_conf.keep_alive = self.config["keep_alive"] client_conf.will_topic = f"$oc/devices/{self.config['device_id']}/sys/events/down" client_conf.will_message = json.dumps({ "type": "ABNORMAL_DISCONNECT", "timestamp": time.strftime("%Y%m%dT%H%M%SZ", time.gmtime()) }) self.device = IotDevice(client_conf) self._connect_with_retry() except Exception as e: logger.error(f"Client initialization failed: {str(e)}") raise def _check_network(self) -> bool: """Check network connectivity""" try: with socket.create_connection( (self.config["server_uri"], self.config["port"]), timeout=10 ): return True except Exception as e: logger.warning(f"Network check failed: {str(e)}") return False def _connect_with_retry(self): """Exponential backoff reconnection mechanism""" retry_count = 0 while retry_count < self.max_retries: try: if not self._check_network(): raise ConnectionError("Network unavailable") result = self.device.connect() if result == 0: logger.info(f"Connection successful (attempt {retry_count + 1}/{self.max_retries})") return True wait_time = min(self.base_reconnect_delay * (2 ** retry_count), 60) logger.warning(f"Connection failed, retrying in {wait_time} seconds... (error code: {result})") time.sleep(wait_time) retry_count += 1 except Exception as e: wait_time = min(self.base_reconnect_delay * (2 ** retry_count), 60) logger.error(f"Connection exception: {str(e)}, retrying in {wait_time} seconds") time.sleep(wait_time) retry_count += 1 logger.error("Max retries reached, giving up") return False def is_connected(self) -> bool: """Check connection status""" try: return (self.device is not None and hasattr(self.device, 'get_client') and self.device.get_client().is_connected()) except Exception as e: logger.warning(f"Connection status check exception: {str(e)}") return False def report_traffic_data(self, counts: Dict[str, int]) -> bool: """Data reporting method""" current_time = time.time() if current_time - self.last_report_time < Config.MIN_REPORT_INTERVAL: return False if not self.is_connected(): logger.warning("Connection lost, attempting to reconnect...") if not self._connect_with_retry(): return False try: service = ServiceProperty() service.service_id = self.config["service_id"] service.properties = { "vehicle_in": counts.get('Inbound_Vehicle', 0), "vehicle_out": counts.get('Outbound_Vehicle', 0), "vehicle_total": counts.get('Total_Vehicles', 0), "person_in": counts.get('Inbound_Pedestrian', 0), "person_out": counts.get('Outbound_Pedestrian', 0), "person_total": counts.get('Total_Pedestrians', 0), "timestamp": int(time.time() * 1000) } service.event_time = time.strftime("%Y%m%dT%H%M%SZ", time.gmtime()) result = self.device.get_client().report_properties([service]) if result == 0: self.last_report_time = current_time logger.info(f"Data reported successfully: {service.properties}") return True logger.error(f"Reporting failed, return code: {result}") return False except Exception as e: logger.error(f"Reporting exception: {str(e)}") return False class TrafficMonitor: """Main traffic monitoring program""" def __init__(self): # Hardware configuration self.device = 'cuda' if torch.cuda.is_available() else 'cpu' logger.info(f"Running on: {self.device.upper()}") # Model loading self.model = self._load_model() self.tracker = sv.ByteTrack() self.line_counter = None self.frame_count = 0 self.current_tracks = {} self.track_history = defaultdict(lambda: deque(maxlen=Config.TRACK_HISTORY_LENGTH)) # Visualization tools with custom color settings self.box_annotator = sv.BoundingBoxAnnotator(color_lookup=sv.ColorLookup.TRACK) self.label_annotator = sv.LabelAnnotator(color_lookup=sv.ColorLookup.TRACK) self.line_annotator = sv.LineZoneAnnotator( thickness=2, text_thickness=1, text_scale=0.5 ) # Table properties self.table_position = list(Config.TABLE_POSITION) self.is_dragging = False self.drag_offset = (0, 0) # Huawei Cloud connection try: self.iot_client = HuaweiIoTClient(Config.IOT_CONFIG) except Exception as e: logger.error(f"Huawei IoT client initialization failed: {str(e)}") self.iot_client = None def _load_model(self) -> YOLO: """Load YOLO model""" try: model = YOLO(Config.MODEL_PATH) model.fuse() logger.info(f"Model loaded successfully, detection classes: {model.names}") return model except Exception as e: logger.error(f"Model loading failed: {str(e)}") sys.exit(1) def set_counting_line(self, start: Tuple[int, int], end: Tuple[int, int]): """Set counting line coordinates""" self.line_counter = LineCounter( start_point=sv.Point(*start), end_point=sv.Point(*end) ) logger.info(f"Counting line set: {start} -> {end}") def _draw_stats(self, frame: np.ndarray, counts: Dict[str, int]) -> np.ndarray: """Draw statistics on frame""" stats = [ f"Inbound Vehicle: {counts['Inbound_Vehicle']}", f"Outbound Vehicle: {counts['Outbound_Vehicle']}", f"Total Vehicles: {counts['Total_Vehicles']}", f"Inbound Pedestrian: {counts['Inbound_Pedestrian']}", f"Outbound Pedestrian: {counts['Outbound_Pedestrian']}", f"Total Pedestrians: {counts['Total_Pedestrians']}" ] for i, text in enumerate(stats): cv2.putText( frame, text, (10, 30 + i * 30), cv2.FONT_HERSHEY_SIMPLEX, Config.FONT_SCALE, Config.TEXT_COLOR, 2 ) return frame def _draw_data_table(self, frame: np.ndarray, counts: Dict[str, int], recent_counts: Dict[str, int]) -> np.ndarray: """Draw movable data table""" x, y = self.table_position row_height = Config.TABLE_ROW_HEIGHT col_width = Config.TABLE_COL_WIDTH # Calculate table dimensions num_cols = 3 num_rows = 5 # Header + 4 data rows table_width = num_cols * col_width table_height = num_rows * row_height # Draw table background cv2.rectangle(frame, (x, y), (x + table_width, y + table_height), (40, 40, 40), -1) # Table header headers = ["Metric", "Total", "Last 10s"] for i, header in enumerate(headers): cv2.rectangle(frame, (x + i * col_width, y), (x + (i + 1) * col_width, y + row_height), Config.TABLE_COLORS['header'], -1) cv2.putText(frame, header, (x + i * col_width + 10, y + int(row_height * 0.7)), cv2.FONT_HERSHEY_SIMPLEX, 0.6, Config.TABLE_COLORS['text'], 1) # Data rows rows = [ ("Inbound Vehicle", counts['Inbound_Vehicle'], recent_counts['Inbound_Vehicle']), ("Outbound Vehicle", counts['Outbound_Vehicle'], recent_counts['Outbound_Vehicle']), ("Inbound Pedestrian", counts['Inbound_Pedestrian'], recent_counts['Inbound_Pedestrian']), ("Outbound Pedestrian", counts['Outbound_Pedestrian'], recent_counts['Outbound_Pedestrian']) ] for row_idx, (label, total, recent) in enumerate(rows): bg_color = Config.TABLE_COLORS['row_even'] if row_idx % 2 == 0 else Config.TABLE_COLORS['row_odd'] # Draw row background cv2.rectangle(frame, (x, y + (row_idx + 1) * row_height), (x + table_width, y + (row_idx + 2) * row_height), bg_color, -1) # Draw cell content cv2.putText(frame, label, (x + 10, y + (row_idx + 1) * row_height + int(row_height * 0.7)), cv2.FONT_HERSHEY_SIMPLEX, 0.5, Config.TABLE_COLORS['text'], 1) cv2.putText(frame, str(total), (x + col_width + 10, y + (row_idx + 1) * row_height + int(row_height * 0.7)), cv2.FONT_HERSHEY_SIMPLEX, 0.5, Config.TABLE_COLORS['text'], 1) cv2.putText(frame, str(recent), (x + 2 * col_width + 10, y + (row_idx + 1) * row_height + int(row_height * 0.7)), cv2.FONT_HERSHEY_SIMPLEX, 0.5, Config.TABLE_COLORS['text'], 1) # Draw drag handle (small rectangle at top-right) handle_size = 20 cv2.rectangle(frame, (x + table_width - handle_size, y), (x + table_width, y + handle_size), (0, 255, 255), -1) return frame def _handle_table_drag(self, event, x, y, flags, param): """Mouse callback for table dragging""" table_x, table_y = self.table_position table_width = 3 * Config.TABLE_COL_WIDTH table_height = 5 * Config.TABLE_ROW_HEIGHT handle_size = 20 # Check if mouse is in drag handle area handle_rect = (table_x + table_width - handle_size, table_y, table_x + table_width, table_y + handle_size) if event == cv2.EVENT_LBUTTONDOWN: if (handle_rect[0] <= x <= handle_rect[2] and handle_rect[1] <= y <= handle_rect[3]): self.is_dragging = True self.drag_offset = (x - table_x, y - table_y) elif event == cv2.EVENT_LBUTTONUP: self.is_dragging = False elif event == cv2.EVENT_MOUSEMOVE: if self.is_dragging: # Update table position with offset new_x = x - self.drag_offset[0] new_y = y - self.drag_offset[1] # Keep table within frame bounds frame_height, frame_width = param.shape[:2] new_x = max(0, min(new_x, frame_width - table_width)) new_y = max(0, min(new_y, frame_height - table_height)) self.table_position = [new_x, new_y] def _draw_tracks(self, frame: np.ndarray, detections: sv.Detections) -> np.ndarray: """Draw object trajectories with matching colors""" for xyxy, _, confidence, class_id, tracker_id in detections: if tracker_id is None or confidence < 0.5: continue # Get color based on class color = Config.CLASS_COLORS.get(class_id, (255, 255, 255)) # Default to white if class not found # Calculate center point x1, y1, x2, y2 = xyxy center = (int((x1 + x2) / 2), int((y1 + y2) / 2)) # Update track history self.track_history[tracker_id].append(center) # Draw trajectory line points = list(self.track_history[tracker_id]) for i in range(1, len(points)): cv2.line(frame, points[i - 1], points[i], color, thickness=2) # Draw bounding box with same color cv2.rectangle(frame, (int(x1), int(y1)), (int(x2), int(y2)), color, 2) # Display ID and class label = f"{Config.CLASS_NAMES.get(class_id, 'Unknown')} ID:{tracker_id}" cv2.putText(frame, label, (int(x1), int(y1) - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2) return frame def _update_track_info(self, detections: sv.Detections): """Update tracking object information""" current_tracks = {} for xyxy, _, confidence, class_id, tracker_id in detections: if tracker_id is not None: current_tracks[tracker_id] = (class_id, confidence) self.current_tracks = current_tracks def process_frame(self, frame: np.ndarray) -> np.ndarray: """Process single frame""" try: # Object detection results = self.model(frame, imgsz=640, verbose=False)[0] detections = sv.Detections.from_ultralytics(results) # Object tracking with ByteTrack detections = self.tracker.update_with_detections(detections) self._update_track_info(detections) # Initialize count results counts = { 'Inbound_Vehicle': 0, 'Outbound_Vehicle': 0, 'Inbound_Pedestrian': 0, 'Outbound_Pedestrian': 0, 'Total_Vehicles': 0, 'Total_Pedestrians': 0 } recent_counts = { 'Inbound_Vehicle': 0, 'Outbound_Vehicle': 0, 'Inbound_Pedestrian': 0, 'Outbound_Pedestrian': 0 } if self.line_counter: # Update counter self.line_counter.update(detections) counts = self.line_counter.get_counts() recent_counts = self.line_counter.get_recent_counts(seconds=10) # Draw counting line cv2.line( frame, (self.line_counter.start.x, self.line_counter.start.y), (self.line_counter.end.x, self.line_counter.end.y), Config.LINE_COLOR.as_bgr(), 2 ) # Periodic data reporting if self.frame_count % Config.REPORT_INTERVAL == 0 and self.iot_client: self.iot_client.report_traffic_data(counts) # Draw object trajectories and boxes (now handled together in _draw_tracks) frame = self._draw_tracks(frame, detections) # Display statistics and table frame = self._draw_stats(frame, counts) frame = self._draw_data_table(frame, counts, recent_counts) # Set mouse callback for table dragging cv2.setMouseCallback("Traffic Monitoring", self._handle_table_drag, frame) self.frame_count += 1 return frame except Exception as e: logger.error(f"Frame processing exception: {str(e)}") return frame def interactive_line_setup(frame: np.ndarray) -> Optional[Tuple[Tuple[int, int], Tuple[int, int]]]: """Interactive counting line setup""" points = [] instructions = [ "1. Click to set line start point", "2. Click to set line end point", "3. Press ESC to confirm" ] def mouse_callback(event, x, y, flags, param): if event == cv2.EVENT_LBUTTONDOWN: points.append((x, y)) cv2.circle(frame, (x, y), 5, (0, 0, 255), -1) if len(points) > 1: cv2.line(frame, points[0], points[1], (0, 255, 0), 2) cv2.namedWindow("Set Counting Line") cv2.setMouseCallback("Set Counting Line", mouse_callback) for i, text in enumerate(instructions): cv2.putText(frame, text, (10, 30 + i * 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 255), 2) while True: cv2.imshow("Set Counting Line", frame) key = cv2.waitKey(1) if key == 27 or len(points) >= 2: # ESC key or two points selected break cv2.destroyAllWindows() return (points[0], points[1]) if len(points) >= 2 else None def main(): """Main program entry""" try: # Open default camera (index 0) cap = cv2.VideoCapture(0) if not cap.isOpened(): logger.error("Unable to open camera") return # Set camera resolution (optional, adjust as needed) cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720) # Initialize monitor monitor = TrafficMonitor() # Read a few frames to allow camera to adjust for _ in range(5): ret, frame = cap.read() if not ret: logger.error("Failed to capture initial frames from camera") return # Set counting line using a frame from the camera line_points = interactive_line_setup(frame.copy()) if line_points: monitor.set_counting_line(*line_points) else: logger.info("No counting line set, will only perform object detection") # Main loop while cap.isOpened(): ret, frame = cap.read() if not ret: logger.warning("Camera frame read failed") break # Process frame processed_frame = monitor.process_frame(frame) # Display results cv2.imshow("Traffic Monitoring", processed_frame) key = cv2.waitKey(1) if key == ord('q') or key == 27: # 'q' or ESC to quit logger.info("Program terminated by user") break elif key == ord('r'): # 'r' to reset counting line line_points = interactive_line_setup(frame.copy()) if line_points: monitor.set_counting_line(*line_points) except KeyboardInterrupt: logger.info("Program interrupted by user") except Exception as e: logger.critical(f"Program exception: {str(e)}", exc_info=True) finally: # Release resources if 'cap' in locals() and cap.isOpened(): cap.release() cv2.destroyAllWindows() logger.info("Program exited") if __name__ == "__main__": # Check required dependencies try: import iot_device_sdk_python except ImportError: logger.error("Huawei IoT SDK not found, please install: pip install iot_device_sdk_python") sys.exit(1) # Ignore warning messages warnings.filterwarnings("ignore", category=UserWarning) main()为我修改这个代码改为画两条线,第一个点和第二个点是第一条线,第三个点和第四个点是第二条线,同时计算第一个点的正向行走人数-第二个点正向行走的绝对值,第二个点-第一个点正向行走的绝对值,第一条线正、逆向行走人数,总人数。第二条线正、逆向行走人数,总人数,尽量减少源代码的修改,MQTT协议传送部分不要过大改动
最新发布
08-16
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值