使用 OpenCV 测量物体尺寸

使用 OpenCV 测量物体尺寸

你是否曾经遇到过这样的问题:想要知道计算器的精确尺寸,但手头又没有专业的测量工具?别担心,今天我们就来教大家一个简单又实用的方法,通过一张A4纸就能估算出计算器的宽度和高度,精确到毫米哦!

该算法的主要思想其实非常简单。请看下面图 1 中我们要处理的样本图像。

图 1.本教程中使用的示例图像。

本教程的目的是估算计算器的宽度和高度(以毫米为单位)。为此,我们需要一个已知尺寸的物体作为参考长度。这基本上就是我们使用白纸作为对象背景的原因。纸张尺寸为 A4,这意味着它的宽度和高度分别为 210 毫米和 297 毫米。然后,我们可以借助这些数字获得估计的计算器尺寸。

在开始之前,我们这篇文章分为几个章节:

  1. 导入模块和参数初始化

  2. 图像加载和预处理

  3. 寻找纸张轮廓

  4. 透视变换

  5. 寻找物体轮廓

  6. 边长计算

  7. 将所有内容放在一个函数中

现在,我们从第一个开始。

1. 导入模块及参数初始化

和其他 Python 项目一样,我要做的第一件事就是导入所有必需的模块。在本例中,我们的大部分工作将使用 和 来完成cv2numpymatplotlib仅用于显示图像。

# Codeblock 1``import cv2``import numpy as np``import matplotlib.pyplot as plt

由于模块已导入,我们将初始化一些参数,这些参数是未来计算所需的,您可以在下面的 Codeblock 2 中看到。变量SCALE主要用于我们不希望生成的图像太小。同时,和PAPER_W表示PAPER_H纸张宽度和高度(以毫米为单位)。

# Codeblock 2``SCALE = 3``PAPER_W = 210 * SCALE``PAPER_H = 297 * SCALE

就这样。第一章到此结束,因为这部分没有什么可说的了。

2.图像加载和预处理

之后,我们将创建一个名为和的函数load_image()show_image()我认为这两个函数的名称是不言自明的。它们的详细信息可以在 Codeblock 3 中看到。您可以在下面看到我定义了参数scale(小写),其中我的目的是使输入图像变得有点小,因为原始图像分辨率非常高。但是,从技术上讲,您也可以通过传递大于 1 的值来使其更大。

show_image()另一方面,该函数实现cv2.cvtColor() 了将颜色通道从 BGR 转换为 RGB 的功能。这种转换是必要的,因为 Matplotlib 在颜色通道顺序方面与 OpenCV 的工作方式不同。

# Codeblock 3``def load_image(path, scale=0.7): img = cv2.imread(path) img_resized = cv2.resize(img, (0,0), None, scale, scale)``return img_resized`` ``def show_image(img): img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) plt.figure(figsize=(6,8)) plt.xticks([]) plt.yticks([]) plt.imshow(img) plt.show()

由于上面的两个函数已经初始化,现在我们可以使用它来实际加载图像。这里我决定将参数保留scale为其默认值(0.7),这将导致加载的图像大小为 1120×840 px(原始大小为 1600×1200 px)。

# Codeblock 4``img_original = load_image(path='images/1.jpeg')``show_image(img_original)``print(img_original.shape)

图 2. 要处理的图像尺寸为 1120 x 840 像素。

我上面显示的图像存储在 中img_original。接下来要做的步骤是使用一系列图像处理技术对该图像进行预处理,即灰度转换(#1)、模糊(#2)、Canny 边缘检测(#3)、扩张(#5)和闭合(#6)。所有这些步骤都包含在preprocess_image()Codeblock 5 中的函数中。

# Codeblock 5``def preprocess_image(img, thresh_1=57, thresh_2=232): img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) #1 img_blur = cv2.GaussianBlur(img_gray, (5,5), 1) #2 img_canny = cv2.Canny(img_blur, thresh_1, thresh_2) #3`` kernel = np.ones((3,3)) #4 img_dilated = cv2.dilate(img_canny, kernel, iterations=1) #5 img_closed = cv2.morphologyEx(img_dilated, cv2.MORPH_CLOSE,`` kernel, iterations=4) #6`` img_preprocessed = img_closed.copy()`` img_each_step = {'img_dilated': img_dilated, 'img_canny' : img_canny, 'img_blur' : img_blur, 'img_gray' : img_gray}`` ``return img_preprocessed, img_each_step

在标记为 的行中,和#2的参数分别表示高斯滤波器大小和高斯分布标准差。同时,行中的和是 Canny 边缘检测器用来捕获弱边缘和强边缘的两个阈值。在本例中,我决定将 设置为 57 和232,这些数字是通过反复试验确定的。接下来,我们初始化一个 3×3 内核,其中内核的所有元素都设置为 1(标记为 的行)。然后,这个全 1 内核将在扩张和闭合过程中用作结构元素。(5,5)``1``thresh_1``thresh_2``#3``thresh_1``thresh_2``#4

preprocess_image()函数返回两个值:完全预处理的图像(存储在 中img_preprocessed)和每个预处理阶段的结果(img_each_step以字典形式存储在 中)。该函数的输出如图 3 所示。要进入下一个过程的图像是img_preprocessed(最右边)。

# Codeblock 6img_preprocessed, img_each_step = preprocess_image(img_original)show_image(img_each_step['img_gray'])show_image(img_each_step['img_blur'])show_image(img_each_step['img_canny'])show_image(img_each_step['img_dilated'])show_image(img_preprocessed)

图 3. 从左到右的图像转换序列:灰度、模糊、边缘检测、扩张和闭合。

3. 寻找纸张轮廓

获取预处理后的图像后,接下来要做的是使用 Codeblock 7 中显示的代码查找轮廓。您可以在那里看到我们使用cv2.findContours()( ) 来执行此操作#1。我们还将其cv2.RETR_EXTERNAL作为参数的输入参数传递,因为我们只对捕获图像中检测到的最外层轮廓(即纸张)感兴趣。现在,计算器对象将被忽略。然后,将使用( )mode绘制检测到的轮廓本身。cv2.drawContours()``#2

# Codeblock 7def find_contours(img_preprocessed, img_original, epsilon_param=0.04):contours, hierarchy = cv2.findContours(image=img_preprocessed, mode=cv2.RETR_EXTERNAL, method=cv2.CHAIN_APPROX_NONE)  #1img_contour = img_original.copy()cv2.drawContours(img_contour, contours, -1, (203,192,255), 6)  #2polygons = []for contour in contours:epsilon = epsilon_param * cv2.arcLength(curve=contour, closed=True)  #3polygon = cv2.approxPolyDP(curve=contour, epsilon=epsilon, closed=True)  #4polygon = polygon.reshape(4, 2)  #5polygons.append(polygon)for point in polygon:    img_contour = cv2.circle(img=img_contour, center=point, radius=8, color=(0,240,0), thickness=-1)  #6return polygons, img_contour不仅如此,这里我还尝试使用cv2.approxPolyDP()(#4)来近似轮廓形状。这行代码的目的是获取纸张轮廓的四个角,然后将坐标存储在其中polygon。我们需要注意的一件事是epsilon行中使用的参数#3。较小的 epsilon 值往往会导致检测到更多的角,而另一方面,较大的 epsilon 会导致函数cv2.approxPolyDP()捕获多边形的一般形状,即较少的角。注意 epsilon 值很重要,因为我们需要确保函数将准确捕获四个角点。

需要执行数组重塑 ( #5),因为 的原始输出cv2.approxPolyDP()格式为(number of corners, 1, 2),其中中间轴在我们的例子中无关紧要。因此,我们可以放心地将其丢弃。除了函数之外find_contours(),我们还将使用cv2.circle()( #6) 显示角。然后,此函数将返回角坐标本身 ( polygon) 和具有突出显示轮廓的图像 ( img_contour)。

下面的代码块 8 显示了我如何调用该find_contours()函数。在这里我决定将设置epsilon_param为 0.04。如果您使用自己的图片,则可能需要更改此值,特别是如果光照特性与我的图像不同。下面代码块的输出(显示在图 4 中)显示了轮廓和角落的样子。我也打印了存储在中的坐标polygon[0]。如果您想知道,使用索引器 0 是因为该find_contours()函数本质上能够捕获多个轮廓,而在这种情况下,我们唯一的外部轮廓是纸张本身。除此之外,可能值得注意的是,存储在中的坐标polygons(x,y)格式,而不是(y,x)

# Codeblock 8polygons, img_contours = find_contours(img_preprocessed, img_original,epsilon_param=0.04)show_image(img_contours)polygons[0]

图 4. 轮廓(粉色)和角落(绿色)的样子。

4.透视变换

由于已经检测到纸张角坐标,现在我们要根据这四个点来扭曲图像。这个过程的目的是在我们开始寻找物体轮廓之前将纸张拉直。

重新排序坐标

说到拉直过程,我们需要知道的一件事是,由于函数的性质,检测到的多边形角可能没有排序cv2.approxPolyDP()。为了使这四个点都有序,我们需要创建一个专门的函数来执行此操作。我正在谈论的函数称为,reorder_coords()其详细信息可在 Codeblock 9 中看到。

# Codeblock 9``def reorder_coords(polygon): rect_coords = np.zeros((4, 2))`` ``add = polygon.sum(axis=1) rect_coords[0] = polygon[np.argmin(add)] # Top left rect_coords[3] = polygon[np.argmax(add)] # Bottom right`` subtract = np.diff(polygon, axis=1) rect_coords[1] = polygon[np.argmin(subtract)] # Top right rect_coords[2] = polygon[np.argmax(subtract)] # Bottom left`` ``return rect_coords

上述函数的工作原理是将两个坐标数字相加和相减,得到 argmin 和 argmax。这些代码行神奇地将左上角、右上角、左下角和右下角分别放在索引 0、1、2 和 3 处。然后,我们可以将此函数应用于存储在中的点,polygon[0]如 Codeblock 10 所示。

# Codeblock 10``rect_coords = np.float32(reorder_coords(polygons[0]))``rect_coords

图 5. 我们使用reorder_coords()函数排序的纸张的四个角点。

稍后,上方重新排序的纸张角坐标(rect_coords)将作为变换的源,而变换目标(paper_coords)由实际纸张大小决定,即PAPER_WPAPER_H。查看 Codeblock 11 以了解我如何手动排列 存储的点。这里要记住的一件事是,目标坐标的顺序需要与源坐标的顺序完全匹配,这就是我们实现重新排序源坐标的功能paper_coords的原因。reorder_coords()

# Codeblock 11``paper_coords = np.float32([[0,0], # Top left [PAPER_W,0], # Top right [0,PAPER_H], # Bottom left [PAPER_W,PAPER_H]]) # Bottom right``paper_coords

图 6.用于图像转换的目标坐标。

除了代码块 10 和 11 之外,您可能还注意到我将数组数据类型转换为 float32。事实上,我尝试使用其他数据类型,例如 int32 和 float64,结果发现这两种数据类型都导致cv2.getPerspectiveTransform()后续代码块中的函数返回错误。

创建变换矩阵

此时,我们已经得到了rect_coordspaper_coords。我们现在可以使用它们来扭曲原始图像,使用cv2.getPerspectiveTransform()和,cv2.warpPerspective()如下面的代码块 12 所示。为了让代码更简洁,我将它们放在另一个名为的函数中warp_image()

# Codeblock 12``def warp_image(rect_coords, paper_coords, img_original, pad=5):`` ``matrix = cv2.getPerspectiveTransform(src=rect_coords, dst=paper_coords) #1``img_warped = cv2.warpPerspective(img_original, matrix,``(PAPER_W, PAPER_H)) #2`` ``warped_h = img_warped.shape[0]``warped_w = img_warped.shape[1]``img_warped = img_warped[pad:warped_h-pad, pad:warped_w-pad] #3`` ``return img_warped

让我们深入研究上述函数。我们首先使用cv2.getPerspectiveTransform()( #1) 创建所谓的变换矩阵。变换矩阵本身的尺寸为 3 × 3,它存储了有关如何将图像从一个角度变换到另一个角度的信息。然后,该矩阵将实际用于使用cv2.warpPerspective()( #2) 变换原始图像。然后,我们将变换后的图像存储在名为 的变量中img_warped。除了函数之外warp_image(),我们还将丢弃图像边界附近的区域 ( #3),因为生成的图像可能在边缘处包含一个狭窄的不需要的黑色区域。

函数的使用warp_image()在 Codeblock 13 中演示,其中输出显示在图 7 中。

# Codeblock 13``img_warped = warp_image(rect_coords, paper_coords, img_original)``show_image(img_warped)``print(img_warped.shape)

图 7.扭曲的图像。

5. 查找物体轮廓

由于原始图像已根据纸张形状进行了扭曲,接下来我将执行完全相同的过程以检测计算器对象,即图像预处理和轮廓搜索。由于要执行的过程与之前的过程相同,因此我们可以简单地重用我们之前定义的函数。在这种情况下,我们的内部轮廓(即计算器按钮)将被忽略,这要归功于cv2.RETR_EXTERNAL我们在 Codeblock 7 中实现的轮廓。

现在,Codeblock 14 和 15 展示了如何进行预处理和轮廓查找。

# Codeblock 14``img_warped_preprocessed, _ = preprocess_image(img_warped)``show_image(img_warped_preprocessed)

图 8.已预处理的扭曲图像。

# Codeblock 15``polygons_warped, img_contours_warped = find_contours(img_warped_preprocessed, img_warped,``epsilon_param=0.04)``show_image(img_contours_warped)``polygons_warped[0]

图 9. 检测到的轮廓(粉色)和角落(绿色)。

由于上面两个Codeblocks中的代码都已经运行完毕,现在所有角点坐标(绿色圆圈)都存储在 中polygons_warped,这四个坐标值其实就是用来估算边长的坐标值。

6. 边长计算

在这种情况下,我们假设纸张上方的所有物体都是矩形。因此,可以通过计算物体左上角和左下角之间的欧几里得距离来估计物体的高度(Codeblock 16 #2)。同时,可以通过计算物体左上角和右上角之间的相同距离度量来获得宽度(#3)。此外,我们需要记住,返回的检测到的角find_contours()仍然是无序的。因此,我们需要reorder_coords()事先调用( )。我想在 Codeblock 16 中强调的最后一件事是,估计的高度和宽度现在存储在按相应顺序#1命名的数组中( )sizes``#4

# Codeblock 16``def calculate_sizes(polygons_warped):`` ``rect_coords_list = []``for polygon in polygons_warped:``rect_coords = np.float32(reorder_coords(polygon)) #1``rect_coords_list.append(rect_coords)`` ``heights = []``widths = []``for rect_coords in rect_coords_list:``height = cv2.norm(rect_coords[0], rect_coords[2], cv2.NORM_L2) #2``width = cv2.norm(rect_coords[0], rect_coords[1], cv2.NORM_L2) #3`` ``heights.append(height)``widths.append(width)`` ``heights = np.array(heights).reshape(-1,1)``widths = np.array(widths).reshape(-1,1)`` ``sizes = np.hstack((heights, widths)) #4`` ``return sizes, rect_coords_list`` ``sizes, rect_coords_list = calculate_sizes(polygons_warped)``sizes``

图 10. 计算器的高度(索引 0)和宽度(索引 1)(以像素为单位)。

转换为毫米

但是,我们需要记住,图 10 中的输出仍然是像素数。要将这些值转换为毫米,我们需要为此创建一个单独的函数,我将其命名为convert_to_mm()(Codeblock 17)。此函数通过取纸张长度(以毫米为单位)和像素(以像素为单位)的比率来工作。然后,我们可以通过将比率值(和)与仍以像素为单位的计算器大小(和#1#2相乘来获得实际的毫米长度。scale_h``scale_w``#3``#4

# Codeblock 17``def convert_to_mm(sizes_pixel, img_warped):``warped_h = img_warped.shape[0]``warped_w = img_warped.shape[1]`` ``scale_h = PAPER_H / warped_h #1``scale_w = PAPER_W / warped_w #2`` ``sizes_mm = []`` ``for size_pixel_h, size_pixel_w in sizes_pixel:``size_mm_h = size_pixel_h * scale_h / SCALE #3``size_mm_w = size_pixel_w * scale_w / SCALE #4`` ``sizes_mm.append([size_mm_h, size_mm_w])`` ``return np.array(sizes_mm)`` ``sizes_mm = convert_to_mm(sizes, img_warped)``sizes_mm

图 11. 已转换为毫米的计算器高度和宽度。

到目前为止,我们已经成功获得了边缘的长度(以毫米为单位)。现在,我们将以文本的形式显示这些值,这些文本写在扭曲的图像上。为此完成的整个过程都放在函数内部write_size()。初始化函数后,我们可以直接调用它,如#1代码块 18 中所示。此代码的输出如图 12 所示。

看起来我们的代码如预期那样工作了。

# Codeblock 18``def write_size(rect_coords_list, sizes, img_warped):`` img_result = img_warped.copy()`` ``for rect_coord, size in zip(rect_coords_list, sizes):`` top_left = rect_coord[0].astype(int) top_right = rect_coord[1].astype(int) bottom_left = rect_coord[2].astype(int)`` cv2.line(img_result, top_left, top_right, (255,100,50), 4) cv2.line(img_result, top_left, bottom_left, (100,50,255), 4)`` cv2.putText(img_result, f'{np.int32(size[0])} mm',`` (bottom_left[0]-20, bottom_left[1]+50), `` cv2.FONT_HERSHEY_DUPLEX, 1, (100,50,255), 1)`` cv2.putText(img_result, f'{np.int32(size[1])} mm',`` (top_right[0]+20, top_right[1]+20), `` cv2.FONT_HERSHEY_DUPLEX, 1, (255,100,50), 1)`` ``return img_result`` ``img_result = write_size(rect_coords_list, sizes_mm, img_warped) #1``show_image(img_result)``print(img_result.shape)

图 12. 在图像上添加文字。

7. 将所有内容放在一个函数中

由于我试图解释此项目中代码使用的每个部分,因此我们上述执行的所有步骤似乎很长。事实上,到目前为止您看到的所有代码都可以包装在一个函数中,我measure_size()在 Codeblock 19 中将其命名为该函数。使用此函数,我们可以简单地将要处理的图像与参数一起传递,以完成我们刚刚完成的所有工作。

# Codeblock 19``def measure_size(path, img_original_scale=0.7,``PAPER_W=210, PAPER_H=297, SCALE=3, paper_eps_param=0.04, objects_eps_param=0.05, canny_thresh_1=57, canny_thresh_2=232):`` ``PAPER_W = PAPER_W * SCALE``PAPER_H = PAPER_H * SCALE`` # Loading and preprocessing original image.``img_original = load_image(path=path, scale=img_original_scale)``img_preprocessed, img_each_step = preprocess_image(img_original, thresh_1=canny_thresh_1, thresh_2=canny_thresh_2)`` # Finding paper contours and corners.``polygons, img_contours = find_contours(img_preprocessed, img_original, epsilon_param=paper_eps_param)`` # Reordering paper corners.``rect_coords = np.float32(reorder_coords(polygons[0]))`` # Warping image according to paper contours.``paper_coords = np.float32([[0,0], [PAPER_W,0], [0,PAPER_H],``[PAPER_W,PAPER_H]])``img_warped = warp_image(rect_coords, paper_coords, img_original)`` # Preprocessing the warped image.``img_warped_preprocessed, _ = preprocess_image(img_warped)`` # Finding contour in the warped image.``polygons_warped, img_contours_warped = find_contours(img_warped_preprocessed, img_warped,``epsilon_param=objects_eps_param)`` # Edge langth calculation.``sizes, rect_coords_list = calculate_sizes(polygons_warped)``sizes_mm = convert_to_mm(sizes, img_warped)``img_result = write_size(rect_coords_list, sizes_mm, img_warped)`` ``return img_result

一旦measure_size()创建了函数,我们现在就可以在几个测试用例上测试它。图 13 所示的输出表明,我们估算物体大小的方法对于不同的矩形物体非常有效。

# Codeblock 20``show_image(measure_size('images/1.jpeg'))``show_image(measure_size('images/2.jpeg'))``show_image(measure_size('images/3.jpeg'))``show_image(measure_size('images/4.jpeg'))``show_image(measure_size('images/5.jpeg'))``show_image(measure_size('images/6.jpeg', objects_eps_param=0.1))

图 13.其他图像上的结果。

一些局限

尽管在许多情况下我们的方法都运行正常,但这并不一定意味着我们的工作是完美的,即使在受控环境中也是如此。如果你仔细观察,你可能会注意到大多数预测的角点实际上并不位于实际的角点位置,这可能会导致测量结果有点不准确。这主要是因为角点的确定高度依赖于二值图像(即闭运算后的图像)的质量。这意味着在这种情况下输入参数值的确定非常关键。

此外,如果我们查看图 13 中从右侧开始的第二张图像,您会发现对象尺寸没有打印出来。这可能是因为由于对象和纸张之间的细微颜色差异,轮廓检测不太好。此外,在我们的最后一张测试图像(最右边的一张)中,尽管对象的整体外观呈矩形,但我们的实现似乎难以准确测量具有弧形角的对象的尺寸。

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

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

相关文章

了解边缘计算,在制造行业使用边缘计算。

边缘计算是一种工业元宇宙技术,可以帮助组织实现其数据的全部潜力。 处理公司的所有数据可能具有挑战性,而边缘计算可以帮助公司更快地处理数据。在制造业中,边缘计算可以帮助进行预测性维护和自动驾驶汽车操作等工作。 什么是边缘计算? …

CMake 编译项目

一、概述 cmake 是C一个很重要的编译和项目管理工具,我们在git 上以及常见的项目现在多数都是用cmake 管理的,那么我们今天就做一个同时有Opencv和CGAL 以及PCL 的项目。 二、项目管理 重点是CMakeList.txt 1、CMakeList.txt cmake_minimum_requir…

FebHost:CO域名在搜索引擎排名中是否高于.COM域名?

.CO 域名在搜索引擎结果中有可能取得高于 .COM 域名的排名,但要注意的是,域名的后缀本身并不会直接影响其搜索排名。决定网站在搜索引擎中的排名的主要因素是搜索引擎优化(SEO)实践的有效性,包括内容的质量、关键词的使…

Quarto Dashboards 教程 2:Dashboard Layout

「写在前面」 学习一个软件最好的方法就是啃它的官方文档。本着自己学习、分享他人的态度,分享官方文档的中文教程。软件可能随时更新,建议配合官方文档一起阅读。推荐先按顺序阅读往期内容: 1.quarto 教程 1:Hello, Quarto 2.qu…

医学影像图像去噪:滤波器方法、频域方法、小波变换、非局部均值去噪、深度学习与稀疏表示和字典学习

医学影像图像去噪是指使用各种算法从医学成像数据中去除噪声,以提高图像质量和对疾病的诊断准确性。MRI(磁共振成像)和CT(计算机断层扫描)是两种常见的医学成像技术,它们都会受到不同类型噪声的影响。 在医学影像中,噪声可能来源于多个方面,包括成像设备的电子系统、患…

支持中文繁体,支持同时配置并启用飞书和Lark认证,JumpServer堡垒机v3.10.8 LTS版本发布

2024年4月22日,JumpServer开源堡垒机正式发布v3.10.8 LTS版本。JumpServer开源项目组将对v3.10 LTS版本提供长期的支持和优化,并定期迭代发布小版本。欢迎广大社区用户升级至v3.10 LTS最新版本,以获得更佳的使用体验。 在v3.10.8 LTS版本中&…

java-Arrays

一、Arrays的概述 Arrays是操作数组的工具类 二、Arrays的常用方法 Arrays的常用方法基本上都被static静态修饰,因此在使用这些方法时,可以直接通过类名调用 1.toString 语法:Arrays.toString(数组) 用于将数组的元素转换为一个字符串&a…

分享三个转换速度快、准确率高的视频转文字工具

想要直接将视频转换成文字,转换工具很重要!给大家分享三个转换速度快、准确率高的视频转文字工具,轻松完成转换。 1.网易见外 https://sight.youdao.com/ 网易家的智能转写翻译服务工作站,网页端就可以直接使用,支持视…

ubuntu apt update:The repository ‘xxx‘ is not signed.报错解决办法(未解决)

文章目录 报错原因及解决办法 报错 rootjax:~# apt update Get:1 file:/var/cuda-repo-l4t-11-4-local InRelease [1575 B] Get:2 file:/var/cudnn-local-repo-ubuntu2004-8.4.1.50 InRelease [1575 B] Get:1 file:/var/cuda-repo-l4t-11-4-local InRelease [1575 B] Get:2 …

[图解]软件开发中的糊涂用语-04-为什么要追究糊涂用语

0 00:00:00,030 --> 00:00:05,620 今天呢,我们来说一个为什么要追究糊涂用语的问题 1 00:00:06,310 --> 00:00:06,548 2 00:00:06,548 --> 00:00:11,077 大家知道我们前些天都发了好几个视频 3 00:00:11,077 --> 00:00:13,461 追究这个糊涂用语 4 00…

COCONut:打造下一代通用分割数据集,重塑计算机视觉基准

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…

医院敏感文件交互 如何保障安全和效率?

医院会产生大量的敏感文件,这些敏感文件交互时,都需要使用特殊的手段,来保障数据的安全性。 医院的敏感数据主要包括以下几类: 1、患者基本信息:包括患者的姓名、身份证号码、户籍地或现住址、联系方式、文化程度、既…