曲面(弧面、柱面)展平(拉直)瓶子标签识别ocr

news2025/2/24 13:24:32

瓶子或者柱面在做字符识别的时候由于变形,识别效果是很不好的

或者是检测瓶子表面缺陷的时候效果也没有展平的好

下面介绍两个项目,关于曲面(弧面、柱面)展平(拉直)

项目一:通过识别曲面的6个点展开

图1 

如 图1所示,通过A、B、C、D、E、F六个点,对柱面展成平面,对应公式可参考下图(图2)

用这个项目的前提是,需要找到这6个点,和通过机器视觉的算法或者是深度学习的算法来实现。 

 图2

1、 项目一代码

import cv2
import numpy as np


BLACK_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 params
        If the line is vertical, set "vertical" attr to True and save "x" position of the line
        """
        self.point1 = point1
        self.point2 = point2
        self.vertical = False
        self.fixed_x = None
        self.k = None
        self.b = None

        # cached angle props
        self.angle = None
        self.angle_cos = None
        self.angle_sin = None

        self.set_line_props(point1, point2)

    def is_vertical(self):
        return self.vertical

    def 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.k
        else:
            self.vertical = True
            self.fixed_x = point2[0]

            k_normal = 0

        self.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_x
        else:
            return int(round(float(y - self.b) / self.k))

    def get_y(self, x):
        return self.k * x + self.b


class LabelUnwrapper(object):
    COL_COUNT = 30
    ROW_COUNT = 20

    def __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/height

        In 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_image
        self.width = self.src_image.shape[1]
        self.height = src_image.shape[0]

        self.dst_image = None
        self.points = pixel_points
        self.percent_points = percent_points

        self.point_a = None  # top left
        self.point_b = None  # top center
        self.point_c = None  # top right
        self.point_d = None  # bottom right
        self.point_e = None  # bottom center
        self.point_f = None  # bottom left

        self.center_line = None
        self.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 = points

        self.points = np.array(self.points)
        (self.point_a, self.point_b, self.point_c,
         self.point_d, self.point_e, self.point_f) = self.points

        center_top = (self.point_a + self.point_c) / 2
        center_bottom = (self.point_d + self.point_f) / 2

        self.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_image

    def 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 griddata

        width, 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] = dst

    def 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 = point
            if x > max_x:
                max_x = x
            if x < min_x:
                min_x = x
            if y > max_y:
                max_y = y
            if y < min_y:
                min_y = y

        return 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_index
                row.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_image

        cv2.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 mask

    def 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 mask

    def 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, 180
        else:
            start_angle, end_angle = 180, 360

        cv2.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_COLOR
        else:
            color = BLACK_COLOR

        cv2.ellipse(img, center_point, axis, angle, 0, 360, color=color, thickness=-1)

    def get_ellipse_params(self, left, top, right):
        center = (left + right) / 2
        center_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 - right
        angle = np.arctan(float(y) / x) * 57.296

        is_arc = False
        if (top - center)[1] > 0:
            is_arc = True

        return is_arc, center_point, axis, angle

    def calc_ellipse_points(self, left, top, right, points_count):
        center = (left + right) / 2

        # get ellipse axis
        a = np.linalg.norm(left - right) / 2
        b = np.linalg.norm(center - top)

        # get start and end angles
        if (top - center)[1] > 0:
            delta = np.pi / (points_count - 1)

        else:
            delta = - np.pi / (points_count - 1)

        cos_rot = (right - center)[0] / a
        sin_rot = (right - center)[1] / a

        points = []
        for i in range(points_count):
            phi = i * delta
            dx, 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_a
        top_right = self.point_c
        bottom_right = self.point_d
        bottom_left = self.point_f

        width1 = 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_height


if __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 np
 
img = 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:
               pass
           else:
               blank[y , x, :] = img[point_y , point_x ,:]
   return blank
 
waved_img = cylindrical_projection(img,500)
imshow(waved_img)

 拓展二:弧面表拉直(展平)

 图12

 图 13

 用了项目三中的代码将弧形表进行展开,发现两侧的刻度过度拉伸,直接用的话效果不是很好,还需对代码进行调整才能使用,不过为弧度表的表盘识别提供了新方向。

------------------------------------------------------------

声明 | 未经允许,禁止转载,谢谢合作!

作者 | 大胡子大叔

出品 | CSDN

-------------------------------------------------------------

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

报名开启 | HarmonyOS第一课“营”在暑期系列直播

<HarmonyOS第一课>2023年再次启航&#xff01; 特邀HarmonyOS布道师云集华为开发者联盟直播间 聚焦HarmonyOS 4版本新特性 邀您一同学习赢好礼&#xff01; 你准备好了吗&#xff1f; ↓↓↓预约报名↓↓↓ 点击关注了解更多资讯&#xff0c;报名学习

[C++]笔记-制作自己的静态库

一.静态库的创建 在项目属性c/c里面,选用无预编译头,创建头文件与cpp文件,需要注意release模式下还是debug模式,在用库时候要与该模式相匹配,库的函数实现是外界无法看到的,最后在要使用的项目里面导入.h文件和.lib文件 二.使用一个循环给二维数组赋值 行数 : 第几个元素 / …

一文带你了解CMS收集器:并发低停顿收集器

一、工作流程 CMS&#xff08;Concurrent Mark Sweep&#xff09;收集器是一种以获取最短回收停顿时间为目标的收集器。互联网网站或者基于B/S系统&#xff08;B/S系统是指Browser/Server系统&#xff0c;也就是基于浏览器和服务器的系统架构&#xff09;的服务端应用通常会关…

ADC静态特性测试

测试环境搭建&#xff1a; 码密度分析法的局限性 更新&#xff1a; MATLAB R2020a之后的版本&#xff0c;更新了函数 “inldnl()”&#xff0c;可以自动计算INL和DNL。具体用法看MATLAB说明文档即可。

Linux —— 进程间通信

目录 一&#xff0c;进程间通信 二&#xff0c;管道 匿名管道 命名管道 一&#xff0c;进程间通信 进程间通信&#xff08;IPC&#xff0c;InterProcess Communication&#xff09;&#xff0c;即在不同进程之间进行信息的传播或交换&#xff1b;由于一般进程用户地址空间是…

C++ STL容器适配器(详解)

STL容器适配器 什么是适配器&#xff0c;C STL容器适配器详解 在详解什么是容器适配器之前&#xff0c;初学者首先要理解适配器的含义。 其实&#xff0c;容器适配器中的“适配器”&#xff0c;和生活中常见的电源适配器中“适配器”的含义非常接近。我们知道&#xff0c;无…

Python土力学与基础工程计算.PDF-螺旋板载荷试验

python 求解代码如下&#xff1a; 1. import numpy as np 2. 3. # 已知参数 4. p_a 100 # 标准压力&#xff0c; kPa 5. p np.array([25, 50, 100, 200) # 荷载&#xff0c; kPa 6. s np.array([2.88, 5.28, 9.50, 15.00) / 10 # 沉降量&#xff0c; cm 7. D 10 # 螺旋板直…

opencv直方图与模板匹配

import cv2 #opencv读取的格式是BGR import numpy as np import matplotlib.pyplot as plt#Matplotlib是RGB %matplotlib inline def cv_show(img,name):cv2.imshow(name,img)cv2.waitKey()cv2.destroyAllWindows() 直方图 cv2.calcHist(images,channels,mask,histSize,ran…

2023-8-18 最长连续不重复子序列

题目链接&#xff1a;最长连续不重复子序列 #include <iostream>using namespace std;const int N 100010; int n; int a[N], s[N];int main () {cin >> n;for(int i 0; i < n; i ) cin >> a[i];int res 0;for(int i 0, j 0; i < n; i){s[a[i]];w…

jenkins 是什么?

一、jenkins 是什么&#xff1f; Jenkins是一个开源的、提供友好操作界面的持续集成(CI)工具&#xff0c;起源于Hudson&#xff0c;主要用于持续、自动的构建/测试软件项目、监控外部任务的运行。Jenkins用Java语言编写&#xff0c;可在Tomcat等流行的servlet容器中运行&#…

集简云 x 车邻邦丨实现金蝶云星辰快速集成第三方系统,实现单据自动同步

品牌故事 车邻邦成立于2009年&#xff0c;专注于汽车贴膜及美容装饰服务&#xff0c;核心业务是为高端4S店、4S集团提供汽车精品领域“产品营销施工售后”的一站式解决方案。 公司成立至今已有14年之久&#xff0c;累计服务客户数百家、累计服务车辆百万台次&#xff0c;口碑…

windows结束explorer进程后桌面白屏解决

背景 结束进程时一不小心一起删掉explorer.exe &#xff0c;这个文件结束桌面就一片白 &#xff0c; 解决&#xff1a; 不要关机&#xff0c;同时按键盘上ctrlshiftesc ,重新进入任务管理器&#xff0c;接着点“进程”选项&#xff0c;按左上角文件选项&#xff0c;进入下拉菜单…

2023年Java核心技术面试第二篇(篇篇万字精讲)

目录 四. 强引用&#xff0c;软引用&#xff0c;弱引用&#xff0c;幻象引用之间的区别&#xff1f; 1.前言 2.强引用 2.1 强引用赋值为null 2.2 超过了引用的作用域 2.2.1 描述&#xff1a; 2.2.2 作用域内&#xff1a; 2.2.3 不在作用域内: 3. 软引用&#xff08;SoftRefere…

助力工业物联网,工业大数据之服务域:服务器性能监控Prometheus及项目总结【三十五】

服务器性能监控Prometheus及项目总结 01&#xff1a;目标 服务器性能监控工具 整体作为了解实现部署安装以及监控构建 项目总结 需求分析、技术架构数仓设计&#xff1a;主题划分、分层设计、维度设计优化、问题、数据量及集群规模简历模板 02&#xff1a;监控需求及常见工…

Cat(6):API介绍—Metric

Metric 用于记录业务指标、指标可能包含对一个指标记录次数、记录平均值、记录总和&#xff0c;业务指标最低统计粒度为1分钟。 # Counter Cat.logMetricForCount("metric.key"); Cat.logMetricForCount("metric.key", 3); # Duration Cat.logMetricForDu…

java学习004

常用数据结构对应 php中常用的数据结构是Array数组&#xff0c;相对的在java开发中常用的数据结构是ArrayList和HashMap&#xff0c;它们可以看成是array的拆分&#xff0c;一种简单的对应关系为 PHPJAVAArray: array(1,2,3)ArrayListlArray: array(“name” > “jack”,“…

通过请求头传数据向后端发请求

axios &#xff08;get post请求、头部参数添加&#xff09;傻瓜式入门axios_axiospost请求参数_web_blog的博客-CSDN博客

【第八讲---视觉里程计2】

在图像中提取特征点并计算特征描述&#xff0c;非常耗时 通过计算描述子距离在不同图像中寻找特征匹配&#xff0c;也非常耗时 利用通过匹配点信息计算相机位姿&#xff0c;没什么问题 我们可以采用以下方法进行改进&#xff1a; 光流&#xff1a;通过其他方式寻找匹配点直接法…

原型对象的简单了解

在前面学习java有一个概念叫做继承&#xff0c;方便我们对父类方法、变量等的调用。对前端的学习我们需要让对象可以访问和继承其他对象的属性和方法&#xff0c;就需要了解原型对象&#xff0c;以及原型链。 一、原型 构造函数通过原型分配的函数是所有对象所共享的。每一个构…

SpringBoot Vue 微人事(十)

职位管理前后端对接问题解决 因为mysql字段关联其他表&#xff0c;进行约束了&#xff0c;删除不了的&#xff0c;就报未知错误是不合适的 需要在后端写一个全局异常类 删掉了MySQLIntegrityConstraintViolationException这个异常类才能导包&#xff0c;能用 RestController…