当前位置: 首页 > news >正文

OpenCV入门9——目标识别(车辆统计)

文章目录

  • 图像轮廓
  • 查找轮廓
  • 绘制轮廓
  • 轮廓的面积与周长
  • 多边形逼近与凸包
  • 外接矩形
  • 项目总览【车辆统计】
  • 视频加载【车辆统计】
  • 去背景【车辆统计】
  • 形态学处理【车辆统计】
  • 逻辑处理【车辆统计】
  • 显示信息【车辆统计】

图像轮廓

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

查找轮廓

# -*- coding: utf-8 -*-
import cv2
import numpy as npimg = cv2.imread('./contours1.jpeg')
# print(img.shape)# 转变为单通道
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 二值化
ret, binary = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY)
# print(gray.shape)cv2.imshow('img', img)
cv2.imshow('binary', binary)# 轮廓查找
contours, hierarchy = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)print(contours)key = cv2.waitKey(0) & 0xff
if key == ord('q'):cv2.destroyAllWindows()

在这里插入图片描述
在这里插入图片描述

绘制轮廓

在这里插入图片描述

# -*- coding: utf-8 -*-
import cv2
import numpy as npimg = cv2.imread('./contours1.jpeg')
# print(img.shape)# 转变为单通道
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 二值化
ret, binary = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY)
# print(gray.shape)# 轮廓查找
contours, hierarchy = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)print(contours)# 绘制轮廓
cv2.drawContours(img, contours, -1, (0, 255, 0), 1)cv2.imshow('img', img)
cv2.imshow('binary', binary)key = cv2.waitKey(0) & 0xff
if key == ord('q'):cv2.destroyAllWindows()

在这里插入图片描述
详细可参考官方资料

# -*- coding: utf-8 -*-
import cv2
import numpy as npimg = cv2.imread('./contours1.jpeg')
# print(img.shape)# 转变为单通道
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 二值化
ret, binary = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY)
# print(gray.shape)# 轮廓查找
contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)print(contours)# 绘制轮廓
cv2.drawContours(img, contours, -1, (0, 255, 0), 1)cv2.imshow('img', img)
cv2.imshow('binary', binary)key = cv2.waitKey(0) & 0xff
if key == ord('q'):cv2.destroyAllWindows()

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

轮廓的面积与周长

在这里插入图片描述
在这里插入图片描述

# -*- coding: utf-8 -*-
import cv2
import numpy as npimg = cv2.imread('./contours1.jpeg')
# print(img.shape)# 转变为单通道
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 二值化
ret, binary = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY)
# print(gray.shape)# 轮廓查找
contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)print(contours)# 绘制轮廓
cv2.drawContours(img, contours, 0, (0, 255, 0), 1)
# 计算面积
area = cv2.contourArea(contours[0])
print("area=%d"%(area))# 计算周长
len = cv2.arcLength(contours[0], True)
print("len=%d"%(len))# cv2.imshow('img', img)
# cv2.imshow('binary', binary)# key = cv2.waitKey(0) & 0xff
# if key == ord('q'):
#     cv2.destroyAllWindows()

在这里插入图片描述

多边形逼近与凸包

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

# -*- coding: utf-8 -*-
import cv2
import numpy as npimg = cv2.imread('./hand.png')
# print(img.shape)# 转变为单通道
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 二值化
ret, binary = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY)
# print(gray.shape)# 轮廓查找
contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)print(len(contours))# 绘制轮廓
cv2.drawContours(img, contours, 0, (0, 255, 0), 1)
# 计算面积
# area = cv2.contourArea(contours[0])
# print("area=%d"%(area))# 计算周长
# len = cv2.arcLength(contours[0], True)
# print("len=%d"%(len))cv2.imshow('img', img)
# cv2.imshow('binary', binary)key = cv2.waitKey(0) & 0xff
if key == ord('q'):cv2.destroyAllWindows()

在这里插入图片描述

# -*- coding: utf-8 -*-
import cv2
import numpy as npdef drawShape(src, points):i = 0while i < len(points):if(i == len(points) - 1):x, y = points[i][0]x1, y1 = points[0][0]cv2.line(src, (x, y), (x1, y1), (0, 255, 0), 2)else:x, y = points[i][0]x1, y1 = points[i + 1][0]cv2.line(src, (x, y), (x1, y1), (0, 255, 0), 2)i = i + 1img = cv2.imread('./hand.png')
# print(img.shape)# 转变为单通道
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 二值化
ret, binary = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY)
# print(gray.shape)# 轮廓查找
contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)# print(len(contours))# 绘制轮廓
# cv2.drawContours(img, contours, 0, (0, 255, 0), 1)
# 计算面积
# area = cv2.contourArea(contours[0])
# print("area=%d"%(area))# 计算周长
# len = cv2.arcLength(contours[0], True)
# print("len=%d"%(len))e = 5
approx = cv2.approxPolyDP(contours[0], e, True)
drawShape(img, approx)hull = cv2.convexHull(contours[0])
drawShape(img, hull)cv2.imshow('img', img)
# cv2.imshow('binary', binary)key = cv2.waitKey(0) & 0xff
if key == ord('q'):cv2.destroyAllWindows()

在这里插入图片描述

外接矩形

在这里插入图片描述
红框就是最小外接矩形,绿框就是最大外接矩形。

最小外接矩形可以看图形有没有旋转
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
详情见参考文档
在这里插入图片描述

# -*- coding: utf-8 -*-
import cv2
import numpy as npdef drawShape(src, points):i = 0while i < len(points):if(i == len(points) - 1):x, y = points[i][0]x1, y1 = points[0][0]cv2.line(src, (x, y), (x1, y1), (0, 255, 0), 2)else:x, y = points[i][0]x1, y1 = points[i + 1][0]cv2.line(src, (x, y), (x1, y1), (0, 255, 0), 2)i = i + 1img = cv2.imread('./hello.jpeg')
# print(img.shape)# 转变为单通道
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 二值化
ret, binary = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY)
# print(gray.shape)# 轮廓查找
contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)# print(len(contours))# 绘制轮廓
# cv2.drawContours(img, contours, 1, (0, 255, 0), 1)
# 计算面积
# area = cv2.contourArea(contours[0])
# print("area=%d"%(area))# 计算周长
# len = cv2.arcLength(contours[0], True)
# print("len=%d"%(len))# e = 5
# 多边形逼近
# approx = cv2.approxPolyDP(contours[0], e, True)
# drawShape(img, approx)# 凸包
# hull = cv2.convexHull(contours[0])
# drawShape(img, hull)r = cv2.minAreaRect(contours[1])
box = cv2.boxPoints(r)
box = np.int0(box)
cv2.drawContours(img, [box], 0, (0, 255, 0), 2)x, y, w, h = cv2.boundingRect(contours[1])
cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 2)cv2.imshow('img', img)
# cv2.imshow('binary', binary)key = cv2.waitKey(0) & 0xff
if key == ord('q'):cv2.destroyAllWindows()

在这里插入图片描述

项目总览【车辆统计】

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

视频加载【车辆统计】

# -*- coding: utf-8 -*-
import cv2
import numpy as npcap = cv2.VideoCapture('./video.mp4')while True:ret, frame = cap.read()if(ret == True):cv2.imshow('video', frame)key = cv2.waitKey(1)if(key == 27):breakcap.release()
cv2.destroyAllWindows()

在这里插入图片描述

去背景【车辆统计】

如果视频是25fps,即每秒25帧,即1000ms过25帧,那么200ms就走5帧(25/1000*200=5)
在这里插入图片描述
在这里插入图片描述
运动的物体为前景,静止的物体就是背景

详细可以参考官方文档
在这里插入图片描述

# -*- coding: utf-8 -*-
import cv2
import numpy as npcap = cv2.VideoCapture('./video.mp4')bgsubmog = cv2.createBackgroundSubtractorMOG2()
while True:ret, frame = cap.read()if(ret == True):mask = bgsubmog.apply(frame)cv2.imshow('video', mask)key = cv2.waitKey(1)if(key == 27):breakcap.release()
cv2.destroyAllWindows()

在这里插入图片描述

# -*- coding: utf-8 -*-
import cv2
import numpy as npcap = cv2.VideoCapture('./video.mp4')bgsubmog = cv2.createBackgroundSubtractorMOG2()
tst = cv2.createBackgroundSubtractorMOG2()while True:ret, frame = cap.read()if(ret == True):# 灰度图cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)# 去噪(高斯)blur = cv2.GaussianBlur(frame, (3, 3), 5)# 去背景mask = bgsubmog.apply(blur)t = tst.apply(frame)cv2.imshow('video', mask)cv2.imshow('t', t)key = cv2.waitKey(40)if(key == 27):breakcap.release()
cv2.destroyAllWindows()

在这里插入图片描述

形态学处理【车辆统计】

# -*- coding: utf-8 -*-
import cv2
import numpy as npcap = cv2.VideoCapture('./video.mp4')bgsubmog = cv2.createBackgroundSubtractorMOG2()
# tst = cv2.createBackgroundSubtractorMOG2()# 形态学kernel
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
kernel2 = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))while True:ret, frame = cap.read()if(ret == True):# 灰度图cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)# 去噪(高斯)blur = cv2.GaussianBlur(frame, (3, 3), 1)# 去背景mask = bgsubmog.apply(blur)# t = tst.apply(frame)# 腐蚀,去掉图中小斑块erode = cv2.erode(mask, kernel, iterations=1)# 膨胀,还原放大dilate = cv2.dilate(erode, kernel2, iterations=5)# 闭操作,去掉物体内部噪声close = cv2.morphologyEx(dilate, cv2.MORPH_CLOSE, kernel)close = cv2.morphologyEx(close, cv2.MORPH_CLOSE, kernel)contours, hierarchy = cv2.findContours(close, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)for i, c in enumerate(contours):x, y, w, h = cv2.boundingRect(c)cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)cv2.imshow('video', frame)# cv2.imshow('erode', close)key = cv2.waitKey(40)if(key == 27):breakcap.release()
cv2.destroyAllWindows()

在这里插入图片描述
在这里插入图片描述

逻辑处理【车辆统计】

# -*- coding: utf-8 -*-
import cv2
import numpy as npmin_w = 50
min_h = 50
max_w = 800
max_h = 800# 检测线的高度
line_high = 480# 存放有效车辆数组
cars = []# 统计车的数量
carnums = 0# 线的偏移
offset = 10# 求中心点
def center(x, y, w, h):x1 = int(w / 2)y1 = int(h / 2)cx = x + x1cy = y + y1return cx, cycap = cv2.VideoCapture('./video.mp4')bgsubmog = cv2.createBackgroundSubtractorMOG2()
# tst = cv2.createBackgroundSubtractorMOG2()# 形态学kernel
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
kernel2 = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))while True:ret, frame = cap.read()if(ret == True):# print(frame.shape)# (584, 1280, 3)# 灰度图cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)# 去噪(高斯)blur = cv2.GaussianBlur(frame, (3, 3), 1)# 去背景mask = bgsubmog.apply(blur)# t = tst.apply(frame)# 腐蚀,去掉图中小斑块erode = cv2.erode(mask, kernel, iterations=1)# 膨胀,还原放大dilate = cv2.dilate(erode, kernel2, iterations=3)# 闭操作,去掉物体内部噪声close = cv2.morphologyEx(dilate, cv2.MORPH_CLOSE, kernel)close = cv2.morphologyEx(close, cv2.MORPH_CLOSE, kernel)contours, hierarchy = cv2.findContours(close, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)cv2.line(frame, (100, line_high), (1100, line_high), (255, 255, 0), 2)for i, c in enumerate(contours):x, y, w, h = cv2.boundingRect(c)# 对车辆的宽高进行判断,以验证是否是有效车辆isValid = (x >= min_w) and (h >= min_h) and (x <= max_w) and (h <= max_h)if(not isValid):continue# 有效的车cpoint = center(x, y, w, h)cars.append(cpoint)cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)for xc, yc in cars:if(yc > line_high - offset and yc < line_high + offset):carnums += 1cars.remove((xc, yc))print(carnums)cv2.imshow('video', frame)# cv2.imshow('erode', close)key = cv2.waitKey(40)if(key == 27):breakcap.release()
cv2.destroyAllWindows()

在这里插入图片描述

显示信息【车辆统计】

# -*- coding: utf-8 -*-
import cv2
import numpy as npmin_w = 50
min_h = 50
max_w = 800
max_h = 800# 检测线的高度
line_high = 480# 存放有效车辆数组
cars = []# 统计车的数量
carnums = 0# 线的偏移
offset = 10# 求中心点
def center(x, y, w, h):x1 = int(w / 2)y1 = int(h / 2)cx = x + x1cy = y + y1return cx, cycap = cv2.VideoCapture('./video.mp4')bgsubmog = cv2.createBackgroundSubtractorMOG2()
# tst = cv2.createBackgroundSubtractorMOG2()# 形态学kernel
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
kernel2 = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))while True:ret, frame = cap.read()if(ret == True):# print(frame.shape)# (584, 1280, 3)# 灰度图cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)# 去噪(高斯)blur = cv2.GaussianBlur(frame, (3, 3), 1)# 去背景mask = bgsubmog.apply(blur)# t = tst.apply(frame)# 腐蚀,去掉图中小斑块erode = cv2.erode(mask, kernel, iterations=1)# 膨胀,还原放大dilate = cv2.dilate(erode, kernel2, iterations=3)# 闭操作,去掉物体内部噪声close = cv2.morphologyEx(dilate, cv2.MORPH_CLOSE, kernel)close = cv2.morphologyEx(close, cv2.MORPH_CLOSE, kernel)contours, hierarchy = cv2.findContours(close, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)# 画一条检测线cv2.line(frame, (100, line_high), (1100, line_high), (255, 255, 0), 2)for i, c in enumerate(contours):x, y, w, h = cv2.boundingRect(c)# 对车辆的宽高进行判断,以验证是否是有效车辆isValid = (x >= min_w) and (h >= min_h) and (x <= max_w) and (h <= max_h)if(not isValid):continue# 有效的车cpoint = center(x, y, w, h)cars.append(cpoint)cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)cv2.circle(frame, (cpoint), 5, (0, 0, 255), -1)for xc, yc in cars:if(yc > line_high - offset and yc < line_high + offset):carnums += 1cars.remove((xc, yc))print(carnums)cv2.putText(frame, "Cars Count:" + str(carnums), (500, 60), cv2.FONT_HERSHEY_SIMPLEX, 2, (0, 255, 0), 3)cv2.imshow('video', frame)# cv2.imshow('erode', close)key = cv2.waitKey(40)if(key == 27):breakcap.release()
cv2.destroyAllWindows()

在这里插入图片描述
通过实践可以发现传统的目标检测缺点很多,比方说可能重复计数…所以之后我们需要结合深度学习来提高目标检测的精度

之后我会持续更新,如果喜欢我的文章,请记得一键三连哦,点赞关注收藏,你的每一个赞每一份关注每一次收藏都将是我前进路上的无限动力 !!!↖(▔▽▔)↗感谢支持!

相关文章:

OpenCV入门9——目标识别(车辆统计)

文章目录 图像轮廓查找轮廓绘制轮廓轮廓的面积与周长多边形逼近与凸包外接矩形项目总览【车辆统计】视频加载【车辆统计】去背景【车辆统计】形态学处理【车辆统计】逻辑处理【车辆统计】显示信息【车辆统计】 图像轮廓 查找轮廓 # -*- coding: utf-8 -*- import cv2 import n…...

2023前端大厂高频面试题之JavaScript篇(5)

系列文章: 2023前端大厂高频面试题之JavaScript篇(1) 2023前端大厂高频面试题之JavaScript篇(2) 2023前端大厂高频面试题之JavaScript篇(3) 2023前端大厂高频面试题之JavaScript篇(4) 2023前端大厂高频面试题之JavaScript篇(5) 2023前端大厂高频面试题之HTML篇 2023前端大厂高…...

物联网网关在工业行业的应用案例

物联网网关在工业行业的应用案例 随着物联网技术的不断发展&#xff0c;物联网网关在工业行业的应用越来越广泛。本文将介绍一个物联网网关在工业行业的应用案例&#xff0c;以期为相关领域的研究和实践提供借鉴和启示。 一、案例背景 某大型制造企业是一家全球知名的汽车制…...

5、基础入门——资产架构端口应用WAF站库分离负载均衡

资产架构 目录型网站安全&#xff1a;一个IP对应一个域名&#xff08;bbs.xiaodi8.com&#xff09;&#xff0c;该域名&#xff08;bbs.xiaodi8.com&#xff09;下有一个网站&#xff0c;该域名的某个目录下&#xff08;bbs.xiaodi8.com/blog&#xff09;也有一个网站。 端口型…...

golang学习笔记——接口和继承比较1

继承 Go 语言的设计之初&#xff0c;就不打算支持面向对象的编程特性&#xff0c;因此 Go 不支持面向对象的三大特性之一——继承。但是 Go 可以通过组合的思想去实现 “继承”。继承是面向对象的三大特性之一&#xff0c;继承是从已有的类中派生出新的类&#xff0c;新的类能…...

chatGPT快捷键(最新版本)

chatGPT 快捷键&#xff0c;可以用于获取最新的一条回复内容 ChatGPT的API接口相当贵&#xff0c;有了快捷键功能&#xff0c;我们可以使用python的selenium控件模拟点击来实现自动化功能&#xff0c;通过发送快捷键来获取最新的回复内容 快捷键介绍如下&#xff1a; windows…...

77基于matlab的蚁群优化路径算法,二维路径和三维路径优化

基于matlab的蚁群优化路径算法&#xff0c;二维路径和三维路径优化。输出可视化最优路径和距离迭代曲线。数据可更换自己的&#xff0c;程序已调通&#xff0c;可直接运行。 77三维和二维路径可视化 (xiaohongshu.com)...

PyTorch中并行训练的几种方式

❤️觉得内容不错的话&#xff0c;欢迎点赞收藏加关注&#x1f60a;&#x1f60a;&#x1f60a;&#xff0c;后续会继续输入更多优质内容❤️ &#x1f449;有问题欢迎大家加关注私戳或者评论&#xff08;包括但不限于NLP算法相关&#xff0c;linux学习相关&#xff0c;读研读博…...

基于非链式(数组)结点结构的二叉树的层序输入创建以及遍历

点击链接返回标题->基于非链式(数组)结点结构的二叉树的层序、先序、中序、后序输入创建以及层序、先序、中序、后序输出-CSDN博客 层序可谓是最简单的二叉树遍历了。。。。 代码很浅显易懂&#xff0c;相信你能明白的&#xff01; #include<iostream> using namesp…...

云计算:开辟数字时代的无限可能

云计算是一项革命性的技术&#xff0c;为企业和个人提供了灵活、可扩展和高效的计算资源。本文将介绍云计算的概念、架构和优势&#xff0c;并探讨其在数字化时代的重要性和未来发展趋势。 引言 随着信息技术的日新月异和数字化转型的浪潮席卷全球&#xff0c;云计算作为一种颠…...

Django+Vue项目创建 跑通

参考链接&#xff1a; 【精选】DjangoVue项目构建_django vue-CSDN博客 一、背景 主要介绍如何使用后端Django 前端Vue 的技术栈快速地搭建起一套web项目的框架。 为什么使用Django和Vue? Django是Python体系下最成熟的web框架之一&#xff0c;由于Python语言的易用…...

2023年中职“网络安全“—Linux系统渗透提权②

2023年中职"网络安全"—Linux系统渗透提权② Linux操作系统渗透测试任务环境说明&#xff1a;1. 使用渗透机对服务器信息收集&#xff0c;并将服务器中SSH服务端口号作为flag提交&#xff1b;2. 使用渗透机对服务器信息收集&#xff0c;并将服务器中主机名称作为flag…...

多模态大模型训练数据集汇总介绍

RefCOCO、RefCOCO、RefCOCOg 这三个是从MS-COCO中选取图像得到的数据集&#xff0c;数据集中对所有的 phrase 都有 bbox 的标注。 RefCOCO 共有19,994幅图像&#xff0c;包含142,209个引用表达式&#xff0c;包含50,000个对象实例。RefCOCO 共有19,992幅图像&#xff0c;包含1…...

IDEA中更换java项目JDK

我们打开IDEA 打开项目 然后选择 File 下的 Project Structure 这里 我们下拉选择自己需要的JDK Sources这里 也要设置一下JDK对应版本 然后 上面这个 Project 中 也要设置一下对应jdk的版本 保持一直 然后 我们打开 File 下的 Settings 然后 找到如下图配置 如果JKD版本看…...

C++函数

转载知呼大佬06 - C函数 - 知乎 (zhihu.com) 06 - C函数 本期我们讨论的是 C 中的函数。 函数到底是什么呢&#xff0c;函数就是我们写的代码块&#xff0c;被设计用来执行特定的任务&#xff0c;以后我们学习 class 类的时候&#xff0c;这些块会被称为方法&#xff0c;但是…...

设计模式-命令模式-笔记

“行为变化”模式 在组件的构建过程中&#xff0c;组件行为的变化经常导致组件本身剧烈的变化。“行为变化”模式组件的行为和组件本身进行解耦&#xff0c;从而支持组件行为的变化&#xff0c;实现两者之间的松耦合。 经典模式&#xff1a;Command、Visitor 动机&#xff0…...

酒店品牌纷纷冲击中高端,东呈集团能否“快人一步”?

过去两年酒店行业加速洗牌&#xff0c;“强者恒强”的马太效应正持续凸显。 报告显示&#xff0c;2022年排名前10名的酒店集团分别为锦江国际、华住、首旅如家、格林、东呈集团、尚美数智、亚朵、德胧、逸柏、都市酒店。以上10家酒店集团客房规模在连锁酒店市场占有率为62.36&…...

[hive] posexplode函数

在Hive SQL中&#xff0c;posexplode是一个用于将数组&#xff08;array&#xff09;拆分为多行的函数。 它返回数组中的每个元素以及其在数组中的位置&#xff08;索引&#xff09;作为两列输出。 这是posexplode函数的语法&#xff1a; posexplode(array)其中&#xff0c;…...

C#具名参数(Named Parameters)

在 C# 中&#xff0c;具名参数&#xff08;Named Parameters&#xff09;是一种在方法调用中使用参数名称来指定参数值的技术。通常情况下&#xff0c;我们使用位置参数&#xff08;Positional Parameters&#xff09;来按照方法参数的顺序传递参数值。但是&#xff0c;使用具名…...

Vue3的组件如何通讯

一、defineProps&#xff0c;defineEmits 子组件nameChange.vue <template><div class"title">姓&#xff1a;{{ firstName }}</div><div>名&#xff1a;{{ lastName }}</div>{{ name }}<button click"clickTap">传…...

VS Code插件侧边栏渲染问题诊断与修复实战

1. 项目概述&#xff1a;一个解决特定IDE侧边栏问题的补丁最近在折腾一个老项目&#xff0c;用的是比较早期的开发环境&#xff0c;IDE是VS Code&#xff0c;但配套的插件生态有些年头了。在尝试使用一个名为“Codex”的辅助编码插件时&#xff0c;遇到了一个挺烦人的问题&…...

手把手教你:如何把CANape调试好的A2L文件,无缝迁移到CANoe里用

从CANape到CANoe&#xff1a;A2L文件迁移的工程实践指南 在汽车电子开发领域&#xff0c;A2L文件作为ECU标定与测量的核心载体&#xff0c;其在不同工具间的无缝迁移直接影响着开发效率。当工程师在CANape中完成初步调试后&#xff0c;如何将精心调校的A2L配置完整迁移至CANoe环…...

iOS开发AI助手规则集:提升Swift代码质量与工程效率

1. 项目概述&#xff1a;为Swift/iOS开发者量身定制的Cursor规则集如果你是一名iOS开发者&#xff0c;并且正在使用Cursor这款AI编程助手&#xff0c;那么你很可能经历过这样的时刻&#xff1a;你向它描述一个需求&#xff0c;比如“帮我创建一个遵循MVVM模式的用户列表视图”&…...

Lazytainer:基于模糊匹配的Docker容器智能管理工具实战

1. 项目概述&#xff1a;一个为容器化工作流“减负”的智能工具如果你和我一样&#xff0c;日常工作中需要频繁地与Docker容器打交道&#xff0c;那么你一定对下面这些场景深有感触&#xff1a;为了调试一个服务&#xff0c;你得先docker ps找到容器ID&#xff0c;再docker exe…...

Transformer在基础算术中的挑战与优化实践

1. 问题背景&#xff1a;当Transformer遇上基础算术2017年Transformer架构横空出世时&#xff0c;谁也没想到这个在机器翻译任务上大放异彩的模型&#xff0c;会在简单的乘法运算面前屡屡碰壁。我在实际项目中发现&#xff0c;即便是训练到收敛的Transformer模型&#xff0c;面…...

Vivado约束新手必看:别再搞混get_pins、get_cells和get_ports了(附实战代码解析)

Vivado约束命令深度解析&#xff1a;精准掌握get_pins、get_cells与get_ports的实战技巧 在FPGA设计流程中&#xff0c;XDC约束文件的编写往往是决定项目成败的关键环节。许多初学者在Vivado环境中第一次接触get_pins、get_cells和get_ports等命令时&#xff0c;常常陷入概念混…...

汽车OTA升级技术深度解析:从安全架构到工程实践

1. 汽车OTA升级&#xff1a;从概念到落地的深度拆解作为一名在汽车电子和嵌入式系统领域摸爬滚打了十几年的工程师&#xff0c;我亲眼见证了汽车从一个纯粹的机械产品&#xff0c;演变成一个高度复杂的、由软件定义的“轮上计算机”。在这个过程中&#xff0c;空中下载技术&…...

Cursor AI编程助手深度思考规则:从思维链到工程化实践

1. 项目概述&#xff1a;为AI编程助手注入深度思考的灵魂如果你和我一样&#xff0c;日常重度依赖Cursor这类AI编程助手来写代码、重构项目或者排查问题&#xff0c;那你肯定也遇到过类似的困扰&#xff1a;AI给出的答案有时看起来“很对”&#xff0c;但仔细一琢磨&#xff0c…...

嵌入式RTOS实战:从OpenFelix内核解析到物联网数据采集系统设计

1. 项目概述&#xff1a;一个为嵌入式与物联网而生的开源实时操作系统如果你正在寻找一个轻量、高效且完全开源的实时操作系统&#xff08;RTOS&#xff09;来驱动你的下一个嵌入式或物联网项目&#xff0c;那么fspecii/openfelix绝对值得你花时间深入研究。这个项目并非又一个…...

光纤传输技术在视频工程中的应用与选型指南

1. 光纤传输技术概述在广播电视和专业视频制作领域&#xff0c;光纤传输技术已经成为高质量视频信号传输的黄金标准。作为一名从业15年的视频系统工程师&#xff0c;我见证了这项技术如何彻底改变行业的面貌。记得2008年我第一次接触3G-SDI光纤传输系统时&#xff0c;那种震撼至…...