实时检测跟踪模块

# 实时检测跟踪模块,并将检测跟踪结果保存到数据库中
# -*- coding: utf-8 -*-
import argparse
import os
os.environ["OMP_NUM_THREADS"] = "1"
os.environ["OPENBLAS_NUM_THREADS"] = "1"
os.environ["MKL_NUM_THREADS"] = "1"
os.environ["VECLIB_MAXIMUM_THREADS"] = "1"
os.environ["NUMEXPR_NUM_THREADS"] = "1"
import sys
import platform
import platform
import numpy as np
from pathlib import Path
import torch
import torch.backends.cudnn as cudnn
from shapely.geometry import Polygon
import numpy as np
import matplotlib.pyplot as plt
import pymysql
import time
from datetime import datetime  
import json
FILE = Path(__file__).resolve()
ROOT = FILE.parents[0]  # yolov5 strongsort root directory
WEIGHTS = ROOT / 'weights'
if str(ROOT) not in sys.path:sys.path.append(str(ROOT))  # add ROOT to PATH
if str(ROOT / 'yolov5') not in sys.path:sys.path.append(str(ROOT / 'yolov5'))  # add yolov5 ROOT to PATH
if str(ROOT / 'trackers' / 'strongsort') not in sys.path:sys.path.append(str(ROOT / 'trackers' / 'strongsort'))  # add strong_sort ROOT to PATH
ROOT = Path(os.path.relpath(ROOT, Path.cwd()))  # relative
from yolov5.models.common import DetectMultiBackend
from yolov5.utils.dataloaders import VID_FORMATS, LoadImages, LoadStreams
from yolov5.utils.general import (LOGGER, Profile, check_img_size, non_max_suppression, scale_boxes, check_requirements, cv2,check_imshow, xyxy2xywh, increment_path, strip_optimizer, colorstr, print_args, check_file)
from yolov5.utils.torch_utils import select_device, time_sync
from yolov5.utils.plots import Annotator, colors, save_one_box
from trackers.multi_tracker_zoo import create_trackerdef get_connection():"""创建并返回一个新的数据库连接。"""# 数据库连接信息host = 'localhost'user = 'root'password = '123456'database = 'video_streaming_database'return pymysql.connect(host=host, user=user, password=password, database=database)def ensure_connection(connection):"""确保连接有效。如果连接无效,则重新建立连接。"""if connection is None or not connection.open:print("Connection is invalid or closed. Reconnecting...")return get_connection()return connection@torch.no_grad()
def run(source='0',yolo_weights=WEIGHTS / 'yolov5m.pt',  # model.pt path(s),reid_weights=WEIGHTS / 'osnet_x0_25_msmt17.pt',  # model.pt path,tracking_method='strongsort',tracking_config=None,imgsz=(640, 640),  # inference size (height, width)cam_ip = '192.168.31.97',conf_thres=0.25,  # confidence thresholdiou_thres=0.45,  # NMS IOU thresholdmax_det=1000,  # maximum detections per imagedevice='0',  # cuda device, i.e. 0 or 0,1,2,3 or cpushow_vid=False,  # show resultssave_txt=False,  # save results to *.txtsave_conf=False,  # save confidences in --save-txt labelssave_crop=False,  # save cropped prediction boxessave_trajectories=False,  # save trajectories for each tracksave_vid=True,  # save confidences in --save-txt labelsnosave=False,  # do not save images/videosclasses=None,  # filter by class: --class 0, or --class 0 2 3agnostic_nms=False,  # class-agnostic NMSaugment=False,  # augmented inferencevisualize=False,  # visualize featuresupdate=False,  # update all modelsproject=ROOT / 'runs' / 'track',  # save results to project/namename='exp',  # save results to project/nameexist_ok=False,  # existing project/name ok, do not incrementline_thickness=2,  # bounding box thickness (pixels)hide_labels=False,  # hide labelshide_conf=False,  # hide confidenceshide_class=False,  # hide IDshalf=False,  # use FP16 half-precision inferencednn=False,  # use OpenCV DNN for ONNX inferencevid_stride=1,  # video frame-rate strideretina_masks=False,
):source = str(source)is_file = Path(source).suffix[1:] in (VID_FORMATS)is_url = source.lower().startswith(('rtsp://', 'rtmp://', 'http://', 'https://'))webcam = source.isnumeric() or source.endswith('.txt') or (is_url and not is_file)if is_url and is_file:source = check_file(source)  if not isinstance(yolo_weights, list):  # single yolo modelexp_name = yolo_weights.stemelif type(yolo_weights) is list and len(yolo_weights) == 1:  # single models after --yolo_weightsexp_name = Path(yolo_weights[0]).stemelse:  # multiple models after --yolo_weightsexp_name = 'ensemble'# 结果保存路径project = os.path.join(os.path.dirname(source), (source.split("\\")[-1][:-4])) + "_det"save_dir = increment_path(Path(project), exist_ok=exist_ok)  # increment run(save_dir / 'tracks' if save_txt else save_dir).mkdir(parents=True, exist_ok=True)  # make dir# 载入模型device = select_device(device)model = DetectMultiBackend(yolo_weights, device=device, dnn=dnn, data=None, fp16=half)stride, names, pt = model.stride, model.names, model.ptimgsz = check_img_size(imgsz, s=stride)  # check image sizeif webcam:show_vid = check_imshow()dataset = LoadStreams(source, img_size=imgsz, stride=stride, auto=pt, vid_stride=vid_stride)nr_sources = len(dataset)else:dataset = LoadImages(source, img_size=imgsz, stride=stride, auto=pt)nr_sources = 1tracker_list = []for i in range(nr_sources):tracker = create_tracker(tracking_method, tracking_config, reid_weights, device, half)tracker_list.append(tracker, )if hasattr(tracker_list[i], 'model'):if hasattr(tracker_list[i].model, 'warmup'):tracker_list[i].model.warmup()outputs = [None] * nr_sources# Run trackingseen, windows, dt = 0, [], (Profile(), Profile(), Profile(), Profile())curr_frames, prev_frames = [None] * nr_sources, [None] * nr_sources# 数据库连接信息host = 'localhost'user = 'root'password = '123456'database = 'video_streaming_database'connection = pymysql.connect(host=host, user=user, password=password, database=database)data = []for frame_idx, (path, im, im0s, vid_cap, s) in enumerate(dataset):start_time = time.time()im_Original = im0s# 隔帧操作,实际测试对跟踪计数影响很大if frame_idx % 2 != 0:im_Original_resieze = cv2.resize(im_Original, dsize=None, fx=0.5, fy=0.5, interpolation=cv2.INTER_CUBIC)cv2.imwrite(os.path.join(str(save_dir), cam_ip + "_" + str(frame_idx + 1).zfill(8) + ".jpg"), im_Original_resieze)continuewith dt[0]:im = torch.from_numpy(im).to(device)im = im.half() if half else im.float()  # uint8 to fp16/32im /= 255.0  # 0 - 255 to 0.0 - 1.0if len(im.shape) == 3:im = im[None]  # expand for batch dimwith dt[1]:pred = model(im, augment=augment, visualize=visualize)with dt[2]:pred = non_max_suppression(pred, conf_thres, iou_thres, classes, agnostic_nms, max_det=max_det)# 处理检测结果 for i, det in enumerate(pred):  # detections per imageseen += 1if webcam:  # nr_sources >= 1p, im0, _ = path[i], im0s[i].copy(), dataset.countp = Path(p)  # to Paths += f'{i}: 'txt_file_name = p.namesave_path = str(save_dir / p.name)  # im.jpg, vid.mp4, ...else:p, im0, _ = path, im0s.copy(), getattr(dataset, 'frame', 0)p = Path(p)  # to Pathf# video fileif source.endswith(VID_FORMATS):txt_file_name = p.stemsave_path = str(save_dir / p.name)  # im.jpg, vid.mp4, ...# folder with imgselse:txt_file_name = p.parent.name  # get folder name containing current imgsave_path = str(save_dir / p.parent.name)  # im.jpg, vid.mp4, ...curr_frames[i] = im0s += '%gx%g ' % im.shape[2:]  # print stringannotator = Annotator(im0, line_width=line_thickness, example=str(names))if hasattr(tracker_list[i], 'tracker') and hasattr(tracker_list[i].tracker, 'camera_update'):if prev_frames[i] is not None and curr_frames[i] is not None:  # camera motion compensationtracker_list[i].tracker.camera_update(prev_frames[i], curr_frames[i])if det is not None and len(det):det[:, :4] = scale_boxes(im.shape[2:], det[:, :4], im0.shape).round()  # rescale boxes to im0 sizefor c in det[:, 5].unique():n = (det[:, 5] == c).sum()  # detections per classs += f"{n} {names[int(c)]}{'s' * (n > 1)}, "  # add to stringwith dt[3]:outputs[i] = tracker_list[i].update(det.cpu(), im0)# 处理跟踪结果 if len(outputs[i]) > 0:for j, (output) in enumerate(outputs[i]):bbox = output[0:4]id = output[4]cls = output[5]conf = output[6]bbox_x = int((output[0] + output[2]) / 2)bbox_y = int((output[1] + output[3]) / 2)bbox_w = int(output[2] - output[0])bbox_h = int(output[3] - output[1])if save_vid or save_crop or show_vid:  # Add bbox to imagec = int(cls)  # integer classid = int(id)  # integer idlabel = None if hide_labels else (f'{id} {names[c]}' if hide_conf else \(f'{id} {conf:.2f}' if hide_class else f'{id} {names[c]} {conf:.2f}'))color = colors(c, True)annotator.box_label(bbox, label, color=color)if save_trajectories and tracking_method == 'strongsort':q = output[7]tracker_list[i].trajectory(im0, q, color=color)if save_crop:bbox = np.array(bbox)                        if frame_idx % 12 == 0:save_one_box(bbox.astype(np.int16), im_Original, file = save_dir / f'{id}' /  (cam_ip + "_"+ str(frame_idx + 1).zfill(8) + "_" + str(id).zfill(4) + "_"+ str(int(bbox_x)).zfill(4) + "_"+ str(int(bbox_y)).zfill(4) + "_"+ str(int(bbox_w)).zfill(4) + "_"+ str(int(bbox_h)).zfill(4) + "_"+ str(int(float(conf) * 10000))+ f'.jpg'), BGR=True)# 将检测跟踪中间结果保存到数据库中connection = ensure_connection(connection)  # 确保连接有效# 获取当前日期和时刻  current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')try:with connection.cursor() as cursor:# 插入数据的SQL语句insert_sql = """INSERT INTO new_detection_tracking_results_1 (camera_ip, frame_number, tracking_id, crop_image_path, event_datetime)VALUES (%s, %s, %s, %s, %s);"""# 示例数据data = [(cam_ip, int(frame_idx+1), int(id), save_dir / f'{id}' /  (cam_ip + "_"+ str(frame_idx + 1).zfill(8) + "_" + str(id).zfill(4) + "_"+ str(int(bbox_x)).zfill(4) + "_"+ str(int(bbox_y)).zfill(4) + "_"+ str(int(bbox_w)).zfill(4) + "_"+ str(int(bbox_h)).zfill(4) + "_"+ str(int(float(conf) * 10000))+ f'.jpg'),current_time)]# 执行插入操作cursor.executemany(insert_sql, data)connection.commit()finally:passelse:   pass# # 将检测跟踪的原图,标注图,检测结果保存到数据库中im_Original_resieze = cv2.resize(im_Original, dsize=None, fx=0.5, fy=0.5, interpolation=cv2.INTER_CUBIC)cv2.imwrite(os.path.join(str(save_dir), cam_ip + "_" + str(frame_idx + 1).zfill(8) + ".jpg"), im_Original_resieze)# 保存检测跟踪结果到文件if outputs[0] == None:track_outputs = []else:track_outputs = [[float(x[0] / 2), float(x[1] / 2), float(x[2] / 2), float(x[3] / 2), int(x[4]), float(x[6]), ""]for x in outputs[0]]data_dict = {}for row in track_outputs:key = int(row[4])  value = row data_dict[key] = value json_output_path = os.path.join(str(save_dir), cam_ip + "_" + str(frame_idx + 1).zfill(8) + "_track.json")with open(json_output_path, 'w') as json_file:json.dump(data_dict, json_file, indent=4)# 记录结束时间  end_time = time.time()  # 计算并打印运行时间  print(f"第{frame_idx}帧,程序运行时间: {end_time - start_time}秒")if end_time - start_time >= 0.0833333333333333333333:print(f"第{frame_idx}帧,程序运行时间: {end_time - start_time}秒")if (end_time - start_time < 0.0833333333333333333333):time.sleep(0.0833333333333333333333-end_time+start_time)def parse_opt():parser = argparse.ArgumentParser()parser.add_argument('--yolo-weights', nargs='+', type=Path, default=R'/home/hitsz/yk_workspace/Yolov5_track/weights/train_citys_bdd_4S_crowdhuman_coco_labs_liucl_1215_no_freeze_no_freeze_yolov5m3/weights/v5m_861.pt', help='model.pt path(s)')parser.add_argument('--reid-weights', type=Path, default=R'weights\osnet_x1_0_msmt17.pt')parser.add_argument('--tracking-method', type=str, default='bytetrack', help='strongsort, ocsort, bytetrack')parser.add_argument('--tracking-config', type=Path, default=None)parser.add_argument('--source', type=str, default=R"02_output_0.mp4", help='file/dir/URL/glob, 0 for webcam')  # 下面为输入为摄像头视频流的参数设置# parser.add_argument('--source', type=str, default=R'rtsp://admin:1234qwer@192.168.1.64:554/Streaming/Channels/101', help='file/dir/URL/glob, 0 for webcam')  parser.add_argument('--imgsz', '--img', '--img-size', nargs='+', type=int, default=[640], help='inference size h,w')parser.add_argument('--cam_ip', type=str, default='192.168.31.97')parser.add_argument('--conf-thres', type=float, default=0.45, help='confidence threshold')parser.add_argument('--iou-thres', type=float, default=0.25, help='NMS IoU threshold')parser.add_argument('--max-det', type=int, default=1000, help='maximum detections per image')parser.add_argument('--device', default='cpu', help='cuda device, i.e. 0 or 0,1,2,3 or cpu')parser.add_argument('--show-vid', default=False, action='store_true' , help='display tracking video results')parser.add_argument('--save-txt', default=True, action='store_true', help='save results to *.txt')parser.add_argument('--save-conf', default=True, action='store_true', help='save confidences in --save-txt labels')parser.add_argument('--save-crop', default=True, action='store_true', help='save cropped prediction boxes')parser.add_argument('--save-trajectories', default=True, action='store_true', help='save trajectories for each track')parser.add_argument('--save-vid', default=True, action='store_true', help='save video tracking results')parser.add_argument('--nosave', default=False, action='store_true', help='do not save images/videos')parser.add_argument('--classes', nargs='+', type=int, help='filter by class: --classes 0, or --classes 0 2 3')parser.add_argument('--agnostic-nms', action='store_true', help='class-agnostic NMS')parser.add_argument('--augment', action='store_true', help='augmented inference')parser.add_argument('--visualize', action='store_true', help='visualize features')parser.add_argument('--update', action='store_true', help='update all models')parser.add_argument('--project', default=R"/home/hitsz/yk_web/Yolov5_track/results/test_save_results1", help='save results to project/name')parser.add_argument('--name', default='test', help='save results to project/name')parser.add_argument('--exist-ok', action='store_true', help='existing project/name ok, do not increment')parser.add_argument('--line-thickness', default=2, type=int, help='bounding box thickness (pixels)')parser.add_argument('--hide-labels', default=False, action='store_true', help='hide labels')parser.add_argument('--hide-conf', default=False, action='store_true', help='hide confidences')parser.add_argument('--hide-class', default=False, action='store_true', help='hide IDs')parser.add_argument('--half', action='store_true', help='use FP16 half-precision inference')parser.add_argument('--dnn', action='store_true', help='use OpenCV DNN for ONNX inference')parser.add_argument('--vid-stride', type=int, default=1, help='video frame-rate stride')parser.add_argument('--retina-masks', action='store_true', help='whether to plot masks in native resolution')opt = parser.parse_args()opt.imgsz *= 2 if len(opt.imgsz) == 1 else 1  # expandopt.tracking_config = ROOT / 'trackers' / opt.tracking_method / 'configs' / (opt.tracking_method + '.yaml')print_args(vars(opt))return optdef main(opt):check_requirements(requirements=ROOT / 'requirements.txt', exclude=('tensorboard', 'thop'))run(**vars(opt))if __name__ == "__main__":opt = parse_opt()main(opt)import { createApp, createElementBlock } from 'vue';
import App from './App.vue';
import "@/assets/less/index.less";
import router from "@/router";import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
import {createPinia} from 'pinia'
import "video.js/dist/video-js.css";import "@/api/mock.js";
import api from '@/api/api'
import {useALLDataStore} from "@/stores"function isRoute(to){const routes = router.getRoutes();// 检查是否有匹配的路由return routes.some(route => {// 处理动态路径匹配const regex = new RegExp(`^${route.path.replace(/:\w+/g, '\\w+')}$`);return regex.test(to.path);});
}const pinia = createPinia();
const app = createApp(App);app.config.globalProperties.$api = api;for (const [key, component] of Object.entries(ElementPlusIconsVue)) {app.component(key, component)}app.use(pinia)
const store = useALLDataStore();
app.use(ElementPlus)
store.addMenu(router,"refresh")
app.use(router).mount("#app");

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/477458.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何使用AWS Lambda构建一个云端工具(超详细)

首发地址&#xff08;欢迎大家访问&#xff09;&#xff1a;如何使用AWS Lambda构建一个云端工具&#xff08;超详细&#xff09; 1 前言 1.1 无服务器架构 无服务器架构&#xff08;Serverless Computing&#xff09;是一种云计算服务模型&#xff0c;它允许开发者构建和运行…

网络爬虫总结与未来方向

通过深入学习和实际操作&#xff0c;网络爬虫技术从基础到进阶得以系统掌握。本节将全面总结关键内容&#xff0c;并结合前沿技术趋势与最新资料&#xff0c;为开发者提供实用性强的深度思考和方案建议。 1. 网络爬虫技术发展趋势 1.1 趋势一&#xff1a;高性能分布式爬虫 随…

实验十三 生态安全评价

1 背景及目的 生态安全是生态系统完整性和健康性的整体反映&#xff0c;完整健康的生态系统具有调节气候净化污染、涵养水源、保持水土、防风固沙、减轻灾害、保护生物多样性等功能。维护生态安全对于人类生产、生活、健康及可持续发展至关重要。随着城市化进程的不断推进&…

archlinux安装waydroid

目录 参考资料 注意 第一步切换wayland 第二步安装binder核心模组 注意 开始安装 AUR安裝Waydroid 启动waydroid 设置网络&#xff08;正常的可以不看&#xff09; 注册谷歌设备 安装Arm转译器 重启即可 其他 参考资料 https://ivonblog.com/posts/archlinux-way…

鸿蒙NEXT开发案例:随机数生成

【引言】 本项目是一个简单的随机数生成器应用&#xff0c;用户可以通过设置随机数的范围和个数&#xff0c;并选择是否允许生成重复的随机数&#xff0c;来生成所需的随机数列表。生成的结果可以通过点击“复制”按钮复制到剪贴板。 【环境准备】 • 操作系统&#xff1a;W…

【Android】Service使用方法:本地服务 / 可通信服务 / 前台服务 / 远程服务(AIDL)

1 本地Service 这是最普通、最常用的后台服务Service。 1.1 使用步骤 步骤1&#xff1a;新建子类继承Service类&#xff1a;需重写父类的onCreate()、onStartCommand()、onDestroy()和onBind()方法步骤2&#xff1a;构建用于启动Service的Intent对象步骤3&#xff1a;调用st…

【LeetCode热题100】队列+宽搜

这篇博客是关于队列宽搜的几道题&#xff0c;主要包括N叉树的层序遍历、二叉树的锯齿形层序遍历、二叉树最大宽度、在每个数行中找最大值。 class Solution { public:vector<vector<int>> levelOrder(Node* root) {vector<vector<int>> ret;if(!root) …

双因子认证:统一运维平台安全管理策略

01双因子认证概述 双因子认证&#xff08;Two-Factor Authentication&#xff0c;简称2FA&#xff09;是一种身份验证机制&#xff0c;它要求用户提供两种不同类型的证据来证明自己的身份。这通常包括用户所知道的&#xff08;如密码&#xff09;、用户所拥有的&#xff08;如…

Apple Vision Pro开发002-新建项目配置

一、新建项目 可以选择默认的&#xff0c;也可以选择Universal 3D 二、切换打包平台 注意选择Target SDK为Devices SDk&#xff0c;这种适配打包到真机调试 三、升级新的Input系统 打开ProjectSettings&#xff0c;替换完毕之后引擎会重启 四、导入PolySpatial 修改上图红…

瑞佑液晶控制芯片RA6807系列介绍 (三)软件代码详解 Part.10(让PNG图片动起来)完结篇

RA6807是RA8876M的缩小版&#xff0c;具备RA8876M的所有功能&#xff0c;只将MCU控制接口进行缩减&#xff0c;仅保留SPI-3和I2C接口&#xff0c;其它功能基本相同。 该芯片最大可控制854x600的分辨率&#xff0c;内建64Mbits显存&#xff0c;多个图层&#xff0c;使用起来相当…

机器人SLAM建图与自主导航:从基础到实践

前言 这篇文章我开始和大家一起探讨机器人SLAM建图与自主导航 &#xff0c;在前面的内容中&#xff0c;我们介绍了差速轮式机器人的概念及应用&#xff0c;谈到了使用Gazebo平台搭建仿真环境的教程&#xff0c;主要是利用gmapping slam算法&#xff0c;生成一张二维的仿真环境…

一篇保姆式centos/ubuntu安装docker

前言&#xff1a; 本章节分别演示centos虚拟机&#xff0c;ubuntu虚拟机进行安装docker。 上一篇介绍&#xff1a;docker一键部署springboot项目 一&#xff1a;centos 1.卸载旧版本 yum remove docker docker-client docker-client-latest docker-common docker-latest doc…

Robot | 用 RDK 做一个小型机器人(更新中)

目录 前言架构图开发过程摄像头模型转换准备校准数据使用 hb_mapper makertbin 工具转换模型 底版开发 结语 前言 最近想开发一个小型机器人&#xff0c;碰巧看到了 RDK x5 发布了&#xff0c;参数对于我来说非常合适&#xff0c;就买了一块回来玩。 外设也是非常丰富&#xf…

如何在 UniApp 中实现 iOS 版本更新检测

随着移动应用的不断发展&#xff0c;保持应用程序的更新是必不可少的&#xff0c;这样用户才能获得更好的体验。本文将帮助你在 UniApp 中实现 iOS 版的版本更新检测和提示&#xff0c;适合刚入行的小白。我们将分步骤进行说明&#xff0c;每一步所需的代码及其解释都会一一列出…

软件工程导论 选填题知识点总结

一 原型化方法是一种动态定义需求的方法&#xff0c;提供完整定义的需求不是原型化方法的特征&#xff0c;其特征包括尽快建立初步需求、简化项目管理以及加强用户参与和决策。 软件危机的表现包括用户对已完成的软件系统不满意的现象经常发生、软件产品的质量往往靠不住、软件…

软件测试面试之常规问题

1.描述一下测试过程 类似题目:测试的生命周期 思路:这是一个“范围”很大的题目&#xff0c;而且回答时间一般在3分钟之内&#xff0c;不可能非常详细的描述整个过程&#xff0c;因此答题的思路要从整体结构入手&#xff0c;不要过细。为了保证答案的准确性&#xff0c;可以引…

Linux|内存级文件原理

目录 进程与文件 Linux下的文件系统 文件操作&#xff0c;及文件流 C语言函数 文件流 文件描述符 系统调用操作 系统调用参数 重定向与文件描述符 输出重定向 输入重定向 文件内容属性 Linux下一切皆文件 进程与文件 当我们对文件进行操作时&#xff0c;文件必须…

洛谷 P1722 矩阵 II C语言 记忆化搜索

题目&#xff1a; https://www.luogu.com.cn/problem/P1722 我们按照案例画一下 我们会发现&#xff0c;会出现重复的子结构。 代码如下&#xff1a; #include<iostream> using namespace std; int mem[300][300]; int n; int f[305][305]; int dfs(int x,int red,…

RTSP播放器EasyPlayer.js播放器分辨率高的视频在设置container的宽高较小时,会出现锯齿状的画面效果

流媒体播放器的核心技术及发展趋势展现了其在未来数字生活中的无限潜力。随着技术的不断进步和市场的持续发展&#xff0c;流媒体播放器将在内容创新、用户体验优化以及跨平台互通等方面取得新的突破。对于从业者而言&#xff0c;把握这些趋势并积极应对挑战将是实现成功的关键…

半导体、晶体管、集成电路、芯片、CPU、单片机、单片机最小系统、单片机开发板-概念串联辨析

下面概念定义从小到大串联&#xff1a; 半导体&#xff08;semiconductor&#xff09;&#xff1a; 是一类常温下导电性能介于导体与绝缘体之间的材料&#xff0c;这种材料的导电性可以随着外部环境比如电压、温度、光照的变换而改变&#xff0c;导电特性区别于导体、超导体、…