曲面(弧面、柱面)展平(拉直)瓶子标签识别ocr
瓶子或者柱面在做字符识别的时候由于变形,识别效果是很不好的
或者是检测瓶子表面缺陷的时候效果也没有展平的好
下面介绍两个项目,关于曲面(弧面、柱面)展平(拉直)
项目一:通过识别曲面的6个点展开
图1
如 图1所示,通过A、B、C、D、E、F六个点,对柱面展成平面,对应公式可参考下图(图2)
用这个项目的前提是,需要找到这6个点,和通过机器视觉的算法或者是深度学习的算法来实现。
图2
1、 项目一代码
import cv2
import numpy as npBLACK_COLOR = (0, 0, 0)
WHITE_COLOR = (255, 255, 255)
YELLOW_COLOR = (0, 255, 255)
RED_COLOR = (0, 0, 255)class Line(object):def __init__(self, point1, point2):"""For line formula y(x) = k * x + b, calc k and b paramsIf the line is vertical, set "vertical" attr to True and save "x" position of the line"""self.point1 = point1self.point2 = point2self.vertical = Falseself.fixed_x = Noneself.k = Noneself.b = None# cached angle propsself.angle = Noneself.angle_cos = Noneself.angle_sin = Noneself.set_line_props(point1, point2)def is_vertical(self):return self.verticaldef set_line_props(self, point1, point2):if point2[0] - point1[0]:self.k = float(point2[1] - point1[1]) / (point2[0] - point1[0])self.b = point2[1] - self.k * point2[0]k_normal = - 1 / self.kelse:self.vertical = Trueself.fixed_x = point2[0]k_normal = 0self.angle = np.arctan(k_normal)self.angle_cos = np.cos(self.angle)self.angle_sin = np.sin(self.angle)def get_x(self, y):if self.is_vertical():return self.fixed_xelse:return int(round(float(y - self.b) / self.k))def get_y(self, x):return self.k * x + self.bclass LabelUnwrapper(object):COL_COUNT = 30ROW_COUNT = 20def __init__(self, src_image=None, pixel_points=None, percent_points=None):"""Point lists are lists of 6 points - [A, B, C, D, E, F]:param pixel_points: List[Tuple] Points, whose coordinates specified as pixels:param percent_points: List[Tuple] Points, whose coordinates specified as fraction of image width/heightIn both cases points represent figure below:| | | || B | A C| / \ | | \ / |A C | B || | | || | OR | || | | |F D F D| \ / | | \ / || E | | E || | | |So, A-B-C-D-E-F-A polygon represent raw wine label on bottle"""self.src_image = src_imageself.width = self.src_image.shape[1]self.height = src_image.shape[0]self.dst_image = Noneself.points = pixel_pointsself.percent_points = percent_pointsself.point_a = None # top leftself.point_b = None # top centerself.point_c = None # top rightself.point_d = None # bottom rightself.point_e = None # bottom centerself.point_f = None # bottom leftself.center_line = Noneself.load_points()def load_points(self):if self.points is None:points = []for point in self.percent_points:x = int(point[0] * self.width)y = int(point[1] * self.height)points.append((x, y))self.points = pointsself.points = np.array(self.points)(self.point_a, self.point_b, self.point_c,self.point_d, self.point_e, self.point_f) = self.pointscenter_top = (self.point_a + self.point_c) / 2center_bottom = (self.point_d + self.point_f) / 2self.center_line = Line(center_bottom, center_top)if not len(self.points) == 6:raise ValueError("Points should be an array of 6 elements")def unwrap(self, interpolate=False):source_map = self.calc_source_map()if interpolate:self.unwrap_label_interpolation(source_map)else:self.unwrap_label_perspective(source_map)return self.dst_imagedef calc_dest_map(self):width, height = self.get_label_size()dx = float(width) / (self.COL_COUNT - 1)dy = float(height) / (self.ROW_COUNT - 1)rows = []for row_index in range(self.ROW_COUNT):row = []for col_index in range(self.COL_COUNT):row.append([int(dx * col_index),int(dy * row_index)])rows.append(row)return np.array(rows)def unwrap_label_interpolation(self, source_map):"""Unwrap label using interpolation - more accurate method in terms of quality"""from scipy.interpolate import griddatawidth, height = self.get_label_size()dest_map = self.calc_dest_map()grid_x, grid_y = np.mgrid[0:width - 1:width * 1j, 0:height - 1:height * 1j]destination = dest_map.reshape(dest_map.size // 2, 2)source = source_map.reshape(source_map.size // 2, 2)grid_z = griddata(destination, source, (grid_x, grid_y), method='cubic')map_x = np.append([], [ar[:, 0] for ar in grid_z]).reshape(width, height)map_y = np.append([], [ar[:, 1] for ar in grid_z]).reshape(width, height)map_x_32 = map_x.astype('float32')map_y_32 = map_y.astype('float32')warped = cv2.remap(self.src_image, map_x_32, map_y_32, cv2.INTER_CUBIC)self.dst_image = cv2.transpose(warped)def unwrap_label_perspective(self, source_map):"""Unwrap label using transform, unlike unwrap_label_interpolation doesn't require scipy"""width, height = self.get_label_size()self.dst_image = np.zeros((height, width, 3), np.uint8)dx = float(width) / (self.COL_COUNT - 1)dy = float(height) / (self.ROW_COUNT - 1)dx_int = int(np.ceil(dx))dy_int = int(np.ceil(dy))for row_index in range(self.ROW_COUNT - 1):for col_index in range(self.COL_COUNT - 1):src_cell = (source_map[row_index][col_index],source_map[row_index][col_index + 1],source_map[row_index + 1][col_index],source_map[row_index + 1][col_index + 1])dst_cell = np.int32([[0, 0], [dx, 0], [0, dy], [dx, dy]])M = cv2.getPerspectiveTransform(np.float32(src_cell), np.float32(dst_cell))dst = cv2.warpPerspective(self.src_image, M, (dx_int, dy_int))x_offset = int(dx * col_index)y_offset = int(dy * row_index)self.dst_image[y_offset:y_offset + dy_int,x_offset:x_offset + dx_int] = dstdef get_roi_rect(self, points):max_x = min_x = points[0][0]max_y = min_y = points[0][1]for point in points:x, y = pointif x > max_x:max_x = xif x < min_x:min_x = xif y > max_y:max_y = yif y < min_y:min_y = yreturn np.array([[min_x, min_y],[max_x, min_y],[max_x, max_y],[min_x, max_y]])def get_roi(self, image, points):rect = self.get_roi_rect(points)return image[np.floor(rect[0][1]):np.ceil(rect[2][1]),np.floor(rect[0][0]):np.ceil(rect[1][0])]def calc_source_map(self):top_points = self.calc_ellipse_points(self.point_a, self.point_b, self.point_c,self.COL_COUNT)bottom_points = self.calc_ellipse_points(self.point_f, self.point_e, self.point_d,self.COL_COUNT)rows = []for row_index in range(self.ROW_COUNT):row = []for col_index in range(self.COL_COUNT):top_point = top_points[col_index]bottom_point = bottom_points[col_index]delta = (top_point - bottom_point) / float(self.ROW_COUNT - 1)point = top_point - delta * row_indexrow.append(point)rows.append(row)return np.array(rows)def draw_mesh(self, color=RED_COLOR, thickness=1):mesh = self.calc_source_map()for row in mesh:for x, y in row:point = (int(round(x)), int(round(y)))cv2.line(self.src_image, point, point, color=color, thickness=thickness)def draw_poly_mask(self, color=WHITE_COLOR):cv2.polylines(self.src_image, np.int32([self.points]), 1, color)def draw_mask(self, color=WHITE_COLOR, thickness=1, img=None):"""Draw mask, if image not specified - draw to source image"""if img is None:img = self.src_imagecv2.line(img, tuple(self.point_f.tolist()), tuple(self.point_a.tolist()), color, thickness)cv2.line(img, tuple(self.point_c.tolist()), tuple(self.point_d.tolist()), color, thickness)self.draw_ellipse(img, self.point_a, self.point_b, self.point_c, color, thickness)self.draw_ellipse(img, self.point_d, self.point_e, self.point_f, color, thickness)def get_label_contour(self, color=WHITE_COLOR, thickness=1):mask = np.zeros(self.src_image.shape)self.draw_mask(color, thickness, mask)return maskdef get_label_mask(self):"""Generate mask of the label, fully covering it"""mask = np.zeros(self.src_image.shape)pts = np.array([[self.point_a, self.point_c, self.point_d, self.point_f]])cv2.fillPoly(mask, pts, WHITE_COLOR)self.draw_filled_ellipse(mask, self.point_a, self.point_b, self.point_c, True)self.draw_filled_ellipse(mask, self.point_f, self.point_e, self.point_d, False)return maskdef draw_ellipse(self, img, left, top, right, color=WHITE_COLOR, thickness=1):"""Draw ellipse using opencv function"""is_arc, center_point, axis, angle = self.get_ellipse_params(left, top, right)if is_arc:start_angle, end_angle = 0, 180else:start_angle, end_angle = 180, 360cv2.ellipse(img, center_point, axis, angle, start_angle, end_angle, color, thickness)def draw_filled_ellipse(self, img, left, top, right, is_top=False):is_arc, center_point, axis, angle = self.get_ellipse_params(left, top, right)if is_arc ^ is_top:color = WHITE_COLORelse:color = BLACK_COLORcv2.ellipse(img, center_point, axis, angle, 0, 360, color=color, thickness=-1)def get_ellipse_params(self, left, top, right):center = (left + right) / 2center_point = tuple(map(lambda x: int(np.round(x)), center.tolist()))axis = (int(np.linalg.norm(left - right) / 2), int(np.linalg.norm(center - top)))x, y = left - rightangle = np.arctan(float(y) / x) * 57.296is_arc = Falseif (top - center)[1] > 0:is_arc = Truereturn is_arc, center_point, axis, angledef calc_ellipse_points(self, left, top, right, points_count):center = (left + right) / 2# get ellipse axisa = np.linalg.norm(left - right) / 2b = np.linalg.norm(center - top)# get start and end anglesif (top - center)[1] > 0:delta = np.pi / (points_count - 1)else:delta = - np.pi / (points_count - 1)cos_rot = (right - center)[0] / asin_rot = (right - center)[1] / apoints = []for i in range(points_count):phi = i * deltadx, dy = self.get_ellipse_point(a, b, phi)x = round(center[0] + dx * cos_rot - dy * sin_rot)y = round(center[1] + dx * sin_rot + dy * cos_rot)points.append([x, y])points.reverse()return np.array(points)def get_ellipse_point(self, a, b, phi):"""Get ellipse radius in polar coordinates"""return a * np.cos(phi), b * np.sin(phi)def get_label_size(self):top_left = self.point_atop_right = self.point_cbottom_right = self.point_dbottom_left = self.point_fwidth1 = np.linalg.norm(top_left - top_right)width2 = np.linalg.norm(bottom_left - bottom_right)avg_width = int((width1 + width2) * np.pi / 4)height1 = np.linalg.norm(top_left - bottom_left)height2 = np.linalg.norm(top_right - bottom_right)avg_height = int((height1 + height2) / 2)return avg_width, avg_heightif __name__ == '__main__':shape = {"tag": "label", "shape": [{"x": 0.012232142857142842, "y": 0.2219140625},{"x": 0.48655701811449864, "y": 0.14404355243445227},{"x": 0.9632539682539681, "y": 0.2171875},{"x": 0.9466567460317459, "y": 0.7276953125},{"x": 0.48447501824501454, "y": 0.7952298867391453},{"x": 0.023134920634920626, "y": 0.7258984375}]}points = []for point in shape['shape']:points.append([point['x'], point['y']])imcv = cv2.imread('image.jpg', cv2.IMREAD_UNCHANGED)unwrapper = LabelUnwrapper(src_image=imcv, percent_points=points)dst_image = unwrapper.unwrap()for point in unwrapper.points:cv2.line(unwrapper.src_image, tuple(point), tuple(point), color=YELLOW_COLOR, thickness=3)# unwrapper.draw_mesh()cv2.imwrite("image_with_mask.png", imcv)cv2.imwrite("unwrapped.jpg", dst_image)
2、原始代码github地址库:
GitHub - Nepherhotep/unwrap_labels: Algorithm to unwrap labels using edge markers
项目二:对项目一的升级版,实现深度学习曲面标签位置,并进行字符识别
1、通过训练掩膜图像,获得模型后,自动计算6个点的位置
图3 掩膜图像
图5 深度学习后找到的六个点
2、将弧映射至曲面
自己拿了矿泉水瓶做的实验
图6 网格圆柱投影
3、进行展开
图7 展开后效果图
展开前字符识别效果很不好
图8 未展开直接识别字符
图9 展开后字符全部识别出来
图8和图9用的百度飞桨做的字符识别,对中文识别效果很好,项目用到的pytesseract字符库识别效果非常不好,对于广告体的中文字无法识别。
展开流程图
图10 展开流程图
4、项目二github地址:
GitHub - AntoninLeroy/wine_label_reader_toolkit: Computer vision project to read a label on a wine bottle using tensorflow, OpenCV and Tesseract.
项目三依赖的库
Flask==2.0.2
Flask_Cors==3.0.10
imutils==0.5.4
keras==2.8.0
numpy==1.21.5
opencv_python==4.5.5.62
Pillow==9.0.1
pytesseract==0.3.8
scikit_learn==1.0.2
scipy==1.7.3
tensorflow==2.8.0
tqdm==4.62.3
特别说明:项目二用了深度学习,使用框架,依赖gpu,无gpu无法运行,没有gpu的同学可以看项目三,项目三是本人改进的版本
项目三:自己通过视觉算法或者ps生成掩膜图像放置对应的位置即可
1、项目三基础代码
import cv2
import numpy as np
from showVision import *
import json
#日期:2023年8月10日
#作者:大胡子大叔
#托管:csdn
#程序功能:通过掩膜图像和原始图像,对柱形图进行拉伸,或者说是展开,曲面展成平面图形
#之所以修改,是因为cpu电脑无法运行tensorflow和keras的库一直报错,所以直接去掉了,没有用深度学习对识别位置进行检测
#可以通过传统的二维算法将位置提取出来,然后再展开即可
#重要的算法是展开
#倾斜的图像也可以矫正
#原始图像路径
img = cv2.imread("./img/train_and_valid/X/400.png")#遮罩图像路径
mask = cv2.imread("./img/train_and_valid/Y/400.png", 0)#得到遮罩后的图像
image = cv2.bitwise_and(img, img, mask=mask)label = labelVision()
mesh,unwrapped=label.readLabels(mask, img)# 最近邻插值法缩放# 缩放到原来的四分之一
image_scale = cv2.resize(image, (0, 0), fx=0.5, fy=0.5, interpolation=cv2.INTER_NEAREST)
mesh_scale = cv2.resize(mesh, (0, 0), fx=0.5, fy=0.5, interpolation=cv2.INTER_NEAREST)
unwrapped_scale = cv2.resize(unwrapped, (0, 0), fx=0.5, fy=0.5, interpolation=cv2.INTER_NEAREST)
# 显示结果图像
#因为图片尺寸过大,需要缩放窗口,缩放窗口以后,显示窗口有时看不见,所以需要设置一下显示窗口的位置
cv2.imshow('cut', image_scale)
#设置窗口的位置
cv2.moveWindow('cut',100,100)
cv2.waitKey(0)
cv2.imshow('mesh', mesh_scale)
cv2.moveWindow('mesh',100,100)
cv2.waitKey(0)
cv2.imshow('unwrapped', unwrapped_scale)
cv2.moveWindow('unwrapped',100,100)
cv2.waitKey(0)
cv2.destroyAllWindows()
2、项目三依赖的库
imutils
numpy
opencv_python如果不做字符识别可不安装下面的库
pytesseract
曲面(弧面、柱面)展平(拉直)需要自己做一个遮罩层
此代码主要是为了方便嫁接使用
自己用视觉算法识别遮罩即可进行嫁接
里面代码去掉了原始程序对gpu的依赖(即自动检测遮罩层位置,所以需要自己做遮罩层)
如果就想用深度学习识别,不想去掉的话,可以访问原始代码地址
https://github.com/AntoninLeroy/wine_label_reader_toolkit
原始代码包含自动识别、展开、字符识别整个流程
如果只想要柱面展开代码,请自行下载
本里面包含两个版本,一个版本包含字符识别,一个版本不包含字符识别
3、项目三代码下载地址
https://download.csdn.net/download/sunnyrainflower/88228306
扩展一:平面变曲面(平面向柱面投影)
图11
参考链接:柱面投影介绍与python实现(一)_zwx1995zwx的博客-CSDN博客
实现代码
from skimage.io import imread, imshow ,imsave
from skimage.transform import resize
import math
import numpy as npimg = imread('img.jpg')
img = (resize(img , [1000,800])*255).astype(np.uint8)###圆柱投影
def cylindrical_projection(img , f) :rows = img.shape[0]cols = img.shape[1]#f = cols / (2 * math.tan(np.pi / 8))blank = np.zeros_like(img)center_x = int(cols / 2)center_y = int(rows / 2)for y in range(rows):for x in range(cols):theta = math.atan((x- center_x )/ f)point_x = int(f * math.tan( (x-center_x) / f) + center_x)point_y = int( (y-center_y) / math.cos(theta) + center_y)if point_x >= cols or point_x < 0 or point_y >= rows or point_y < 0:passelse:blank[y , x, :] = img[point_y , point_x ,:]return blankwaved_img = cylindrical_projection(img,500)
imshow(waved_img)
拓展二:弧面表拉直(展平)
图12
图 13
用了项目三中的代码将弧形表进行展开,发现两侧的刻度过度拉伸,直接用的话效果不是很好,还需对代码进行调整才能使用,不过为弧度表的表盘识别提供了新方向。
------------------------------------------------------------
声明 | 未经允许,禁止转载,谢谢合作!
作者 | 大胡子大叔
出品 | CSDN
-------------------------------------------------------------
相关文章:

曲面(弧面、柱面)展平(拉直)瓶子标签识别ocr
瓶子或者柱面在做字符识别的时候由于变形,识别效果是很不好的 或者是检测瓶子表面缺陷的时候效果也没有展平的好 下面介绍两个项目,关于曲面(弧面、柱面)展平(拉直) 项目一:通过识别曲面的6个点…...

知识继承概述
文章目录 知识继承第一章 知识继承概述1.背景介绍第一页 背景第二页 大模型训练成本示例第三页 知识继承的动机 2.知识继承的主要方法 第二章 基于知识蒸馏的知识继承预页 方法概览 1.知识蒸馏概述第一页 知识蒸馏概述第二页 知识蒸馏第三页 什么是知识第四页 知识蒸馏的核心目…...

深度剖析数据在内存中的存储
目录 一、数据类型介绍 类型的基本归类 1.整形家族 2.浮点数家族 3.构造类型 (自定义类型) 4.指针类型 5.空类型 二、整形在内存中的存储 1.原码、反码、补码 1.1原码 1.2反码 1.3补码 1.4计算规则 2 .大小端介绍 三、浮点型在内存中的存…...

【ARM Linux 系统稳定性分析入门及渐进10 -- GDB 初始化脚本介绍及使用】
文章目录 gdb 脚本介绍gdb 初始化脚本使用启动 gdb 的时候自动执行脚本gdb运行期间执行命令脚本 gdb 脚本介绍 GDB脚本是一种使用GDB命令语言编写的脚本,可以用来自动化一些常见的调试任务。这些脚本可以直接在GDB中运行,也可以通过GDB的-x参数或source…...

AQS源码解读
文章目录 前言一、AQS是什么?二、解读重点属性statehead、tail 同步变量竞争acquire 同步变量释放 总结 前言 AQS是AbstractQueuedSynchronizer的缩写,也是大神Doug Lea的得意之作。今天我们来进行尽量简化的分析和理解性的代码阅读。 一、AQS是什么&am…...

QT实现天气预报
1. MainWindow类设计的成员变量和方法 public: MainWindow(QWidget* parent nullptr); ~MainWindow(); protected: 形成文本菜单来用来右键关闭窗口 void contextMenuEvent(QContextMenuEvent* event); 鼠标被点击之后此事件被调用 void mousePressEvent(QMouseEv…...

【马蹄集】第二十三周——进位制专题
进位制专题 目录 MT2186 二进制?不同!MT2187 excel的烦恼MT2188 单条件和MT2189 三进制计算机1MT2190 三进制计算机2 MT2186 二进制?不同! 难度:黄金 时间限制:1秒 占用内存:128M 题目…...
[足式机器人]Part3 变分法Ch01-1 数学预备知识——【读书笔记】
本文仅供学习使用 本文参考: 《变分法基础-第三版》老大中 《变分学讲义》张恭庆 《Calculus of Variations of Optimal Control Theory》-变分法和最优控制论-Daneil Liberzon Ch01-1 数学基础-预备知识1 1 数学基础-预备知识1.1 泰勒公式1.1.1 一元函数的泰勒公式…...

计算机网络----CRC冗余码的运算
目录 1. 冗余码的介绍及原理2. CRC检验编码的例子3. 小练习 1. 冗余码的介绍及原理 冗余码是用于在数据链路层的通信链路和传输数据过程中可能会出错的一种检错编码方法(检错码)。原理:发送发把数据划分为组,设每组K个比特&#…...

将Nginx源码数组结构(ngx_array.c)和内存池代码单独编译运行,附代码
在上面一篇的基础上把Nginx源码数组结构也摘录下来,也增加了测试代码,编译运行。 https://blog.csdn.net/katerdaisy/article/details/132358883 《将nginx内存池代码单独编译运行,了解nginx内存池工作原理,附代码》 核心代码&…...

java forEach中不能使用break和continue的原因
1.首先了解break和continue的使用范围和作用 1.1使用范围 break适用范围:只能用于switch或者是循环语句中。当然可以用于增强for循环。 continue适用范围: 用于循环语句中。 1.2作用 break: 1. break用于switch语句的作用是结束一个switch语句。 2. break用于循…...
[杂项]水浒英雄谱系列电影列表
年份 片名 导演 主演 2006-01-01 母夜叉孙二娘 张建亚 周海媚 、 莫少聪 、 于承惠 [1] 2008-01-01 碧瑶霜迷案 黄祖权 陈龙 、 陈德容 、 翁家明 [7] 2008-05-09 青面兽杨志 张建亚 吕良伟 、 计春华 、 孟广美 [2] 2008-05-09 扈三娘与矮脚虎王英 张建亚 曾宝仪 、 郭德纲 、…...

6.RocketMQ之索引文件ConsumeQueue
本文着重分析为consumequeue/topic/queueId目录下的索引文件。 1.ConsumeQueueStore public class ConsumeQueueStore {protected final ConcurrentMap<String>, ConcurrentMap<Integer>, ConsumeQueueInterface>> consumeQueueTable;public boolean load(…...

【C++学习手札】一文带你认识C++虚继承
食用指南:本文在有C基础的情况下食用更佳 🍀本文前置知识:C虚函数(很重要,内部剖析) ♈️今日夜电波:僕らのつづき—柊優花 1:06 ━━━━━━️💟──────── 3:51 …...
神经网络基础-神经网络补充概念-63-残差网络
概念 残差网络(Residual Network,ResNet)是一种深度卷积神经网络结构,旨在解决深层网络训练中的梯度消失和梯度爆炸问题,以及帮助训练非常深的网络。ResNet 在2015年被提出,其核心思想是引入了"残差块…...

【从0开始学架构笔记】01 基础架构
文章目录 一、架构的定义1. 系统与子系统2. 模块与组件3. 框架与架构4. 重新定义架构 二、架构设计的目的三、复杂度来源:高性能1. 单机复杂度2. 集群复杂度2.1 任务分配2.2 任务分解(微服务) 四、复杂度来源:高可用1. 计算高可用…...

vue3+ts+vite使用el-breadcrumb实现面包屑组件,实现面包屑过渡动画
简介 使用 element-plus 的 el-breadcrumb 组件,实现根据页面路由动态生成面包屑导航,并实现面包屑导航的切换过渡动画 一、先看效果加粗样式 1.1 静态效果 1.2 动态效果 二、全量代码 <script lang"ts" setup> import { ref, watch…...

【Java 动态数据统计图】动态数据统计思路案例(动态,排序,数组)四(116)
需求::前端根据后端的返回数据:画统计图; 1.动态获取地域数据以及数据中的平均值,按照平均值降序排序; 说明: X轴是动态的,有对应区域数据则展示; X轴 区域数据降序排序…...
Chrome命令行开关
Electron 支持的命令行开关 –client-certificatepath 设置客户端的证书文件 path . –ignore-connections-limitdomains 忽略用 , 分隔的 domains 列表的连接限制. –disable-http-cache 禁止请求 HTTP 时使用磁盘缓存. –remote-debugging-portport 在指定的 端口 通…...

元宇宙赛道加速破圈 和数软件抓住“元宇宙游戏”发展新风口
当下海外游戏市场仍然具备较大的增长空间。据机构预测,至2025年全球移动游戏市场规模将达1606亿美元,对应2020-2025年复合增长率11%。与此同时,随着元宇宙概念持续升温,国内外多家互联网巨头纷纷入场。行业分析平台New…...
进程地址空间(比特课总结)
一、进程地址空间 1. 环境变量 1 )⽤户级环境变量与系统级环境变量 全局属性:环境变量具有全局属性,会被⼦进程继承。例如当bash启动⼦进程时,环 境变量会⾃动传递给⼦进程。 本地变量限制:本地变量只在当前进程(ba…...
C++:std::is_convertible
C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

练习(含atoi的模拟实现,自定义类型等练习)
一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...
在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module
1、为什么要修改 CONNECT 报文? 多租户隔离:自动为接入设备追加租户前缀,后端按 ClientID 拆分队列。零代码鉴权:将入站用户名替换为 OAuth Access-Token,后端 Broker 统一校验。灰度发布:根据 IP/地理位写…...

cf2117E
原题链接:https://codeforces.com/contest/2117/problem/E 题目背景: 给定两个数组a,b,可以执行多次以下操作:选择 i (1 < i < n - 1),并设置 或,也可以在执行上述操作前执行一次删除任意 和 。求…...
spring:实例工厂方法获取bean
spring处理使用静态工厂方法获取bean实例,也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下: 定义实例工厂类(Java代码),定义实例工厂(xml),定义调用实例工厂ÿ…...

视频字幕质量评估的大规模细粒度基准
大家读完觉得有帮助记得关注和点赞!!! 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用,因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型(VLMs)在字幕生成方面…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)
本期内容并不是很难,相信大家会学的很愉快,当然对于有后端基础的朋友来说,本期内容更加容易了解,当然没有基础的也别担心,本期内容会详细解释有关内容 本期用到的软件:yakit(因为经过之前好多期…...
ip子接口配置及删除
配置永久生效的子接口,2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...
在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?
uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件,用于在原生应用中加载 HTML 页面: 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...