【计算机视觉】基于OpenCV计算机视觉的摄像头测距技术设计与实现

基于计算机视觉的摄像头测距技术

文章目录

  • 基于计算机视觉的摄像头测距技术
    • 导读
    • 引入
    • 技术实现原理
    • 技术实现细节
      • Python-opencv实现方案
      • 获取目标轮廓
        • 步骤 1:图像处理
        • 步骤 2:找到轮廓
        • 步骤完整代码
      • 计算图像距离
        • 前置技术背景与原理
        • 步骤 1:定义距离计算函数
        • 步骤 2:准备调用函数的数据
        • 步骤 3:循环遍历图片并计算距离
    • 完整代码
      • Python
      • C++
      • 运行截图
    • 思路总结
      • 代码逻辑思路
    • 结语

导读

在当今技术日益进步的时代,计算机视觉已成为我们生活中不可或缺的一部分。从智能监控到虚拟现实,计算机视觉技术的应用范围日益广泛。在这篇博客中,我们将探索一个特别实用的计算机视觉案例:使用OpenCV实现摄像头测距。这一技术不仅对专业人士有用,也为编程爱好者和技术创新者提供了广泛的应用可能性。

引入

OpenCV,作为一个功能强大的开源计算机视觉库,已经在全球范围内被广泛应用于各种项目和研究中。其中,摄像头测距是一个极具挑战性且实用的话题。本文将介绍如何利用OpenCV结合相似三角形原理来实现精确的距离测量。无论你是计算机视觉的新手还是有经验的开发者,这篇文章都将为你提供一种新的视角来理解和应用这一领域的基本概念。我们将从相似三角形的基本原理出发,逐步深入,展示如何在实际项目中应用这些知识来实现摄像头测距的功能。。

技术实现原理

使用相似三角形计算物体到相机的距离

在使用相似三角形方法计算摄像头测距时,我们关注的是在不同距离下,同一个物体在相机视野中所占的像素大小变化。这个方法基于一个简单的几何原理:当我们知道某个距离下物体的实际大小和在图像中的大小,就可以推算出在其他距离下的参数。

举一个实际例子,我们可以将此过程的单位转换为厘米来更好地适应中国常用的度量标准。假设我们已知一个物体的真实宽度是 W 厘米,然后将其放置在距离相机 D 厘米的地方进行拍照。在照片中测量该物体的像素宽度为 P 像素,那么可以通过以下公式计算相机的焦距 F(单位为像素):

F = ( P ⋅ D ) / W F = (P \cdot D) / W F=(PD)/W

以实际数据为例,假设我们在距离相机 60.96厘米(大约等于24英寸)的地方放置了一张纸,其宽度为 27.94厘米(大约等于11英寸)。通过图像处理,我们测得照片中纸的像素宽度为 248 像素。那么,焦距 F 计算如下:

F = ( 248 px ⋅ 60.96 cm ) / 27.94 cm ≈ 543.45 px F = (248 \text{px} \cdot 60.96 \text{cm}) / 27.94 \text{cm} ≈ 543.45 \text{px} F=(248px60.96cm)/27.94cm543.45px

现在,无论我们将相机移动得更近或更远,都可以使用相似三角形的原理来计算物体到相机的距离 D’:

D ′ = ( W ⋅ F ) / P D' = (W \cdot F) / P D=(WF)/P

其中,W 是物体的实际宽度(厘米),F 是之前计算得到的焦距(像素),P 是新位置下物体在照片中的宽度(像素)。通过这种方式,我们就能够计算出物体在不同距离下到相机的距离,从而实现精准的测距。

技术实现细节

Python-opencv实现方案

首先,我们需要导入必要的库,并定义一个find_marker函数来定位图像中我们想要测量距离的物体。在这个例子中,我们以一张约A4纸作为目标物体。下面是找到这个目标物体的过程:

from imutils import paths
import numpy as np
import imutils
import cv2# 用于识别要计算距离的物体
def find_marker(image):# 将图像转换为灰度图,然后进行模糊处理,以去除图像中的高频噪声gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)gray = cv2.GaussianBlur(gray, (5, 5), 0)# 使用 Canny 算法进行边缘检测edged = cv2.Canny(gray, 35, 125)# 寻找边缘图像中的轮廓,保留最大的一个,假设这是我们图像中的纸张cnts = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)cnts = imutils.grab_contours(cnts)c = max(cnts, key=cv2.contourArea)# 计算纸张区域的边界框,并返回return cv2.minAreaRect(c)

获取目标轮廓

我们的目标是使用 OpenCV 来识别图像中的物体(例如一张纸),并计算它与摄像头之间的距离。首先,我们需要定义一个函数 find_marker,用于在图片中找到我们要计算距离的目标物体。在这个例子中,我们使用一张 8.5 x 11 英寸的纸作为目标物体。

步骤 1:图像处理
# 导入必要的包
from imutils import paths
import numpy as np
import imutils
import cv2# 将图像转换为灰度图,然后进行模糊处理,以减少噪声,最后进行边缘检测
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray, (5, 5), 0)
edged = cv2.Canny(gray, 35, 125)

在这几行代码中,我们首先将图像转换为灰度图,这是因为灰度图处理起来更加高效,且对于边缘检测来说足够了。然后,我们使用高斯模糊来降低图像的高频噪声,这有助于后续的边缘检测。最后,我们使用 Canny 算法来检测图像中的边缘。

image-20231203205608370

步骤 2:找到轮廓
# 在边缘检测后的图像中找到轮廓,保留最大的那个轮廓
# 我们假设最大的轮廓就是我们的目标物体(比如纸)
cnts = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)
c = max(cnts, key=cv2.contourArea)# 计算物体轮廓的边界框,并返回
return cv2.minAreaRect(c)

这一部分代码用于找出图像中的所有轮廓,然后选择面积最大的轮廓作为目标物体的轮廓。我们使用 cv2.findContours 函数来检测轮廓,并通过 cv2.contourArea 函数找出最大的轮廓。cv2.minAreaRect 函数则用于计算该轮廓的最小面积矩形,这个矩形包含了轮廓的 (x, y) 坐标以及像素长度和宽度。

步骤完整代码
from imutils import paths
import numpy as np
import imutils
import cv2# 用于识别要计算距离的物体
def find_marker(image):# 将图像转换为灰度图,然后进行模糊处理,以去除图像中的高频噪声gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)gray = cv2.GaussianBlur(gray, (5, 5), 0)# 使用 Canny 算法进行边缘检测edged = cv2.Canny(gray, 35, 125)# 寻找边缘图像中的轮廓,保留最大的一个,假设这是我们图像中的纸张cnts = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)cnts = imutils.grab_contours(cnts)c = max(cnts, key=cv2.contourArea)# 计算纸张区域的边界框,并返回return cv2.minAreaRect(c)

阶段总结

  1. 图像预处理:首先,图像被转换为灰度图。灰度图是处理图像的常见方式,因为它简化了分析过程并降低了计算复杂性。接着,对灰度图像应用高斯模糊。这一步骤可以帮助去除图像中的高频噪声,使边缘检测更加准确。
  2. 边缘检测:使用Canny算法进行边缘检测。Canny边缘检测是一种广泛使用的技术,它能够帮助识别图像中物体的轮廓。
  3. 轮廓识别:检测到边缘后,接下来找出图像中所有轮廓,并选择面积最大的轮廓。在这个案例中,假设最大的轮廓是我们要测量距离的目标物体。
  4. 计算包围盒:最后,cv2.minAreaRect函数被用来计算轮廓的最小区域矩形。这个矩形可以用来估计物体的大小和它在图像中的方向,这是后续计算距离所必需的。

接下来,我们将详细探讨如何使用OpenCV和相似三角形原理来计算物体到摄像头的距离。我们会深入每个步骤的技术细节,并解释背后的原理。

计算图像距离

前置技术背景与原理
  • 相似三角形原理:这是计算距离的核心原理。当两个三角形的相应角相等时,它们的边长成比例。在我们的应用中,我们利用这一点来推算物体到摄像头的距离。

  • 焦距的计算与应用:焦距是摄像头镜头中心到成像平面的距离。通过已知距离和物体尺寸,我们可以计算出焦距。然后,使用这个焦距来计算在其他距离下的物体尺寸。

步骤 1:定义距离计算函数
def distance_to_camera(knownWidth, focalLength, perWidth):# 计算并返回从物体到摄像头的距离return (knownWidth * focalLength) / perWidth

这个函数使用三个参数:目标物体的已知宽度(knownWidth)、计算得到的焦距(focalLength)和图像中目标物体的像素宽度(perWidth)。通过相似三角形原理,可以计算出物体到摄像头的距离。

距离计算公式及其解析

函数 distance_to_camera 的核心在于应用相似三角形原理来计算物体到摄像头的距离。这里的计算公式为:

D = W × F P D = \frac{W \times F}{P} D=PW×F
其中,D 代表从物体到摄像头的距离,W 是物体的已知宽度(knownWidth),F 是焦距(focalLength),P 是图像中物体的像素宽度(perWidth)。

公式解析

  1. 已知宽度(W):这是实际物体的宽度,它是我们预先知道的一个固定值,通常用于校准过程。例如,在本例中,如果我们使用一张标准尺寸的纸张,其宽度是一个已知量。

  2. 焦距(F):焦距是相机镜头特性的一部分,表示在光学系统中,光线汇聚成清晰图像的特定距离。在标定过程中通过特定的设置(如已知物体距离和尺寸)计算得出。

  3. 像素宽度(P):这是通过图像处理技术(如边缘检测)从相机拍摄的图像中测量得到的物体的像素宽度。

应用原理

这个公式基于相似三角形的概念。在两个三角形中,如果角度相同,那么它们的边长比例相同。在这种情况下,一侧是实际物体到相机的距离(我们想要计算的),另一侧是物体在相机成像平面上的像素宽度。通过已知的实际宽度和计算出的焦距,我们可以使用比例关系来找出未知的距离。

步骤 2:准备调用函数的数据
# 已知目标物体到摄像头的距离,这里是24英寸
KNOWN_DISTANCE = 24.0# 已知目标物体的宽度,这里是11英寸
KNOWN_WIDTH = 11.0# 加载第一张图片,这张图片中的物体距离摄像头已知,然后找到标记,初始化焦距
image = cv2.imread("images/object.jpg")
marker = find_marker(image)
focalLength = (marker[1][0] * KNOWN_DISTANCE) / KNOWN_WIDTH

在这个准备阶段,我们首先确定目标物体到摄像头的已知距离和物体的已知宽度。然后,我们加载一张物体距离摄像头已知的图片,通过 find_marker 函数找到物体的轮廓,并使用这些信息计算焦距。这里的焦距计算基于相似三角形原理,即在已知一定距离下物体在图像中的尺寸,我们可以推算出在其他距离下的尺寸。

步骤 3:循环遍历图片并计算距离
# 遍历每张图片
for imagePath in sorted(paths.list_images("images")):# 加载图片,找到标记,然后计算摄像头到标记的距离image = cv2.imread(imagePath)marker = find_marker(image)inches = distance_to_camera(KNOWN_WIDTH, focalLength, marker[1][0])# 绘制边界框并展示box = cv2.cv.BoxPoints(marker) if imutils.is_cv2() else cv2.boxPoints(marker)box = np.int0(box)cv2.drawContours(image, [box], -1, (0, 255, 0), 2)cv2.putText(image, "%.2fft" % (inches / 12),(image.shape[1] - 200, image.shape[0] - 20), cv2.FONT_HERSHEY_SIMPLEX,2.0, (0, 255, 0), 3)cv2.imshow("image", image)cv2.waitKey(0)

在这个循环中,我们处理每张图片,使用 find_marker 函数找到物体的轮廓,然后调用 distance_to_camera 函数计算物体到摄像头的距离。结果显示在图片上,包括绘制的边界框和距离信息。

完整代码

Python

import cv2
import numpy as np
import imutils
from imutils import pathsclass DistanceCalculator:def __init__(self, knownWidth, knownDistance):# 初始化已知物体宽度和距离self.knownWidth = knownWidthself.knownDistance = knownDistanceself.focalLength = Nonedef calibrate(self, calibrationImagePath):# 使用一张已知距离的图片进行焦距标定image = cv2.imread(calibrationImagePath)marker = self.find_marker(image)self.focalLength = (marker[1][0] * self.knownDistance) / self.knownWidthdef find_marker(self, image):# 在图像中寻找目标物体的轮廓gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)gray = cv2.GaussianBlur(gray, (5, 5), 0)edged = cv2.Canny(gray, 35, 125)cnts = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)cnts = imutils.grab_contours(cnts)c = max(cnts, key=cv2.contourArea)return cv2.minAreaRect(c)def distance_to_camera(self, perWidth):# 计算物体到摄像头的距离if self.focalLength is None:raise ValueError("Focal length is not calibrated.")return (self.knownWidth * self.focalLength) / perWidthdef process_image(self, imagePath):# 处理单张图片,并显示距离image = cv2.imread(imagePath)marker = self.find_marker(image)distance = self.distance_to_camera(marker[1][0])box = cv2.cv.BoxPoints(marker) if imutils.is_cv2() else cv2.boxPoints(marker)box = np.int0(box)cv2.drawContours(image, [box], -1, (0, 255, 0), 2)cv2.putText(image, "%.2fcm" % (distance * 2.54), # 将英寸转换为厘米(image.shape[1] - 200, image.shape[0] - 20), cv2.FONT_HERSHEY_SIMPLEX,2.0, (0, 255, 0), 3)cv2.imshow("Distance", image)cv2.waitKey(0)# 主程序
if __name__ == "__main__":KNOWN_DISTANCE = 60.96 # 设置已知距离(厘米)KNOWN_WIDTH = 27.94 # 设置已知物体宽度(厘米)calculator = DistanceCalculator(KNOWN_WIDTH, KNOWN_DISTANCE)calculator.calibrate("images/calibration_image.jpg") # 使用已知距离的图片进行焦距标定for imagePath in sorted(paths.list_images("images")):calculator.process_image(imagePath) # 处理每张图片并计算距离cv2.destroyAllWindows() # 关闭所有OpenCV窗口

C++

请确保你已经安装了C++OpenCV环境。Windows下Visual Studio详情参考可以参考:Windows安装Opencv与VS配置

#include <opencv2/opencv.hpp>
#include <iostream>
#include <vector>
#include <algorithm>class DistanceCalculator {
public:DistanceCalculator(float knownWidth, float knownDistance) : knownWidth(knownWidth), knownDistance(knownDistance), focalLength(0.0f) {}void calibrate(const cv::Mat& calibrationImage) {cv::RotatedRect marker = findMarker(calibrationImage);focalLength = (marker.size.width * knownDistance) / knownWidth;}float distanceToCamera(float perWidth) const {if (focalLength == 0.0f) {throw std::logic_error("Focal length is not calibrated.");}return (knownWidth * focalLength) / perWidth;}cv::RotatedRect findMarker(const cv::Mat& image) const {cv::Mat gray, blurred, edged;cv::cvtColor(image, gray, cv::COLOR_BGR2GRAY);cv::GaussianBlur(gray, blurred, cv::Size(5, 5), 0);cv::Canny(blurred, edged, 35, 125);std::vector<std::vector<cv::Point>> contours;cv::findContours(edged, contours, cv::RETR_LIST, cv::CHAIN_APPROX_SIMPLE);std::sort(contours.begin(), contours.end(), [](const std::vector<cv::Point>& c1, const std::vector<cv::Point>& c2) {return cv::contourArea(c1) > cv::contourArea(c2);});return cv::minAreaRect(contours[0]);}private:float knownWidth;float knownDistance;float focalLength;
};int main() 
{float KNOWN_DISTANCE = 60.96f; // cmfloat KNOWN_WIDTH = 27.94f; // cmDistanceCalculator calculator(KNOWN_WIDTH, KNOWN_DISTANCE);cv::Mat calibrationImage = cv::imread("calibration_image.jpg");calculator.calibrate(calibrationImage);std::vector<std::string> imagePaths = { "path_to_images/image1.jpg", "path_to_images/image2.jpg", ... };for (const std::string& path : imagePaths) {cv::Mat image = cv::imread(path);cv::RotatedRect marker = calculator.findMarker(image);float distance = calculator.distanceToCamera(marker.size.width);cv::Point2f points[4];marker.points(points);for (int i = 0; i < 4; i++)cv::line(image, points[i], points[(i+1)%4], cv::Scalar(0, 255, 0), 2);std::string text = std::to_string(distance) + " cm";cv::putText(image, text, cv::Point(10, image.rows - 20), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 255, 0), 2);cv::imshow("Distance", image);cv::waitKey(0);}cv::destroyAllWindows();return 0;
}

运行截图

当你运行结果会有以下输出

image-20231203222713593

image-20231203222844179

思路总结

本项目的目标是使用OpenCV实现摄像头测距,即计算照片中目标物体到相机的距离。我们采用了相似三角形的方法,利用物体在不同距离下在相机成像平面上的尺寸变化来推算实际距离。首先,通过图像处理技术识别并提取目标物体的轮廓,然后计算焦距,并利用已知的物体宽度和图像中的像素宽度来计算物体到摄像头的距离。

代码逻辑思路

在代码实现方面,我们首先定义了一个处理图像和计算距离的类 DistanceCalculator。这个类包含方法来寻找图像中的目标物体轮廓、计算相机焦距、以及最终计算物体到摄像头的距离。

  1. 图像处理和轮廓检测:对于每张输入图像,首先应用图像处理技术(灰度转换、高斯模糊、边缘检测)来准备图像,并使用find_marker方法提取目标物体的轮廓。
  2. 焦距计算:使用一张已知距离的标定图像来计算焦距。这个过程包括测量标定图像中物体的像素宽度,并根据已知的实际宽度和距离计算焦距。
  3. 距离测量:对于每张图像,使用distance_to_camera方法计算物体到摄像头的距离。这依赖于焦距、已知物体的实际宽度以及图像中物体的像素宽度。
  4. 结果展示:在处理后的图像上绘制物体轮廓,并显示计算出的距离。这不仅提供了视觉反馈,也验证了距离计算的准确性。
  5. 主程序流程:实例化DistanceCalculator类,使用标定图像进行焦距计算,然后遍历目标图像集合,对每张图像进行处理和距离计算。
    • __init__: 构造函数,用于初始化已知的物体宽度和距离。
    • calibrate: 通过一张已知距离的图片计算焦距。这一步是关键,因为正确的焦距计算对于后续的距离测量至关重要。
    • find_marker: 在给定的图像中找到目标物体的轮廓。这通过将图像转换为灰度图,应用高斯模糊和Canny边缘检测来完成。
    • distance_to_camera: 使用计算得到的焦距和图像中物体的像素宽度来计算物体到摄像头的距离。

运行逻辑流程图

开始
DistanceCalculator 类
图像处理和轮廓检测
焦距计算
距离测量
结果展示
图像处理: 灰度转换 高斯模糊 边缘检测
提取目标物体轮廓
使用标定图像计算焦距
计算物体到摄像头的距离
在图像上绘制轮廓和显示距离
结束

结语

如果您喜欢我们的文章,请不要忘记点击关注。我们将继续推出更多关于计算机视觉、人工智能、以及C++、Python、Java等技术领域的精彩内容。您的支持是我们不断前进、分享更多知识和见解的最大动力。我们期待与您一起探索这些激动人心的技术领域,共同成长。感谢您的阅读和支持,敬请期待我们的后续文章!

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

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

相关文章

[传智杯 #3 决赛] 面试

题目背景 disangan233 和 disangan333 去面试了&#xff0c;面试官给了一个问题&#xff0c;热心的你能帮帮他们吗&#xff1f; 题目描述 现在有 n 个服务器&#xff0c;服务器 i 最多能处理 ai​ 大小的数据。 接下来会有 k 条指令 bk​&#xff0c;指令 i 表示发送 bi​ …

海德汉(HEIDENHAIN)CNC数据采集(可免授权)

一&#xff0c;概述 海德汉 常见的系统一般有530、640系统&#xff0c;采集一般有两种方法&#xff1a; &#xff08;1&#xff09;购买海德汉官方的SDK&#xff0c;HeidenhainDNC COM Component&#xff0c;安装之后有相应的demo&#xff0c;支持的语言有C#、C/C。此方法还需…

面试篇之微服务(二)

目录 服务容灾 21.什么是服务雪崩&#xff1f; 22.什么是服务熔断&#xff1f;什么是服务降级&#xff1f; 什么是服务熔断&#xff1f; 什么是服务降级&#xff1f; 有哪些熔断降级方案实现&#xff1f; 23.Hystrix怎么实现服务容错&#xff1f; 24.Sentinel怎么实现限…

JSP格式化标签 parseDate将指定时间格式字符串转为真正的date对象

格式化标签最后一个就是 parseDate 作用 将一个日期/时间格式字符串 转为 真正的date时间类型 有点无语 这种 东西应该都是在java中去做的 而不是在java中 这个建议也是做个了解即可 作用不是那么大 基本语法如下 这里 我们 直接编写代码如下 <% page contentType"…

JSP格式化标签 parseNumber指定格式字符串转数字类型

好 我们继续来说格式化标签 parseNumber 它的作用是讲一个字符串 转换为指定格式的数值型 老实说 这东西 作为了解把 实际开发中都不是用得少 我建议还是在java端就处理好 不建议在jsp中高这种类型转换的操作 基本格式如下 这几个属性都是我们这几期jsp标签的老朋友了 我们…

【STM32】STM32学习笔记-新建工程(04)

00. 目录 文章目录 00. 目录01. 创建STM32工程02. STM32工程编译和下载03. LED测试04. 型号分类及缩写05. 工程结构06. 附录 01. 创建STM32工程 【STM32】STM32F103C8T6 创建工程模版详解(固件库) 02. STM32工程编译和下载 2.1 选择下载器位ST-Link Debugger 2.2 勾选上电…

认识成交量VOL,搞懂量价关系

一、认识成交量VOL 1、成交量VOL的含义 VOL是一个成交量指标&#xff0c;是指个股或者大盘一定时间内的成交数量&#xff0c;一般的炒股软件中都是指成交总手数&#xff08;1手100股&#xff09;。 成交量体现在炒股软件上就是一根竖着的柱子&#xff0c;成交量越大&#xff0c…

Redis常见类型

常用类型String字符串类型Hash字典类型List列表类型Set集合类型ZSet有序集合类型 Java程序操作Redis代码操作Redis 常用类型 String字符串类型 使用方式&#xff1a; 使用场景&#xff1a; Hash字典类型 字典类型(Hash) 又被成为散列类型或者是哈希表类型&#xff0c;它…

数据库-MySQL之数据库必知必会22-26章

第 22 章 使用视图 视图是虚拟的表。与包含数据的表不一样&#xff0c;视图只包含使用时动态检索数据的查询。 使用视图 视图用CREATE VIEW语句来创建。 使用SHOW CREATE VIEW viewname&#xff1b;来查看创建视图的语句。 用DROP删除视图&#xff0c;其语法为DROP VIEW view…

开发猿的平平淡淡周末---2023/12/3

2023/12/3 天气晴 温度适宜 AM 早安八点多的世界&#xff0c;起来舒展了下腰&#xff0c;阳光依旧明媚&#xff0c;给平淡的生活带来了一丝暖意 日常操作&#xff0c;喂鸡&#xff0c;时政&#xff0c;洗漱&#xff0c;恰饭&#xff0c;肝会儿游戏 看会儿手机 ___看累…

数据结构 | 查漏补缺之ASL、

目录 ASL 情形之一&#xff1a;二分查找 线索二叉树 哈夫曼树 大根堆 邻接表&邻接矩阵 ASL 参考博文 关于ASL(平均查找长度)的简单总结_平均查找长度asl-CSDN博客 情形之一&#xff1a;二分查找 线索二叉树 参考博文 线索二叉树(线索链表遍历&#xff0c;二叉树…

Unity中Shader指令优化

文章目录 前言解析一下不同运算、条件、函数所需的指令数1、常数基本运算2、变量基本运算3、条件语句、循环 和 函数 前言 上一篇文章中&#xff0c;我们解析了Shader解析后的代码。我们在这篇文章中来看怎么实现Shader指令优化 Unity中Shader指令优化&#xff08;编译后指令…

【深度学习实验】图像处理(四):PIL——自定义图像数据增强操作(图像合成;图像融合(高斯掩码))

文章目录 一、实验介绍二、实验环境1. 配置虚拟环境2. 库版本介绍 三、实验内容0. 导入必要的库1. PIL基础操作2~4. 随机遮挡、随机擦除、线性混合5. 图像合成5.1 原理5.2 实现5.3 效果展示 6. 图像融合6.1 原理6.2 实现6.3 效果展示 一、实验介绍 在深度学习任务中&#xff0c…

MySQL进阶_EXPLAIN重点字段解析

文章目录 第一节.准备1.1 版本信息1.2 准备 第二节.type2.1 system2.2 const2.3 eq_ref2.4 ref2.5 ref_or_null2.6 index_merge2.7 unique_subquery2.8 range2.9 index2.10 all 第三节. Extra3.1 No tables used3.2 No tables used3.3 Using where3.4 No matching min/max row3…

【数据结构高阶】AVL树

上期博客我们讲解了set/multiset/map/multimap的使用&#xff0c;下面我们来深入到底层&#xff0c;讲解其内部结构&#xff1a; 目录 一、AVL树的概念 二、AVL树的实现 2.1 节点的定义 2.2 数据的插入 2.2.1 平衡因子的调整 2.2.1.1 调整平衡因子的规律 2.2.2 子树的旋…

JavaEE 多线程

JavaEE 多线程 文章目录 JavaEE 多线程引子多线程1. 特性2. Thread类2.1 概念2.2 Thread的常见构造方法2.3 Thread的几个常见属性2.4 启动一个线程2.5 中断一个线程2.6 等待一个线程2.7 获取当前线程引用2.8 休眠当前线程 3. 线程状态 引子 当进入多线程这一块内容时&#xff…

2023-12-03 LeetCode每日一题(可获得的最大点数)

2023-12-03每日一题 一、题目编号 1423. 可获得的最大点数二、题目链接 点击跳转到题目位置 三、题目描述 几张卡牌 排成一行&#xff0c;每张卡牌都有一个对应的点数。点数由整数数组 cardPoints 给出。 每次行动&#xff0c;你可以从行的开头或者末尾拿一张卡牌&#x…

使用OpenMVS重建模型

1、数据格式转换 首先将生成的稠密点云以及图片信息转换成openmvs支持的.mvs文件。在openmvs_sample中的bin文件内打开终端 作者&#xff1a;舞曲的小水瓶 https://www.bilibili.com/read/cv25019877/ 出处&#xff1a;bilibili interfaceCOLMAP.exe -i D:\desktop\test\toy\…

【Linux服务器Java环境搭建】05 Node JS安装及环境变量配置

【Linux服务器Java环境搭建】01购买云服务器以及在服务器中安装Linux系统 【Linux服务器Java环境搭建】02 通过xftp和xshell远程连接云服务器 【Linux服务器Java环境搭建】03 Git工具安装 【Linux服务器Java环境搭建】04 JDK安装&#xff08;JAVA环境安装&#xff09; 【Linux服…

flink源码分析 - 命令行参数解析-CommandLineParser

flink版本: flink-1.11.2 调用位置: org.apache.flink.runtime.entrypoint.StandaloneSessionClusterEntrypoint#main 代码位置: flink核心命令行解析器: org.apache.flink.runtime.entrypoint.parser.CommandLineParser /** Licensed to the Apache Software Foundati…