OpenCV 从入门到精通(day_05)

1. 模板匹配

1.1 什么是模板匹配

        模板匹配就是用模板图(通常是一个小图)在目标图像(通常是一个比模板图大的图片)中不断的滑动比较,通过某种比较方法来判断是否匹配成功。

1.2 匹配方法

        res=cv2.matchTemplate(image, templ, method)

  • image:原图像,这是一个灰度图像或彩色图像(在这种情况下,匹配将在每个通道上独立进行)。

  • templ:模板图像,也是灰度图像或与原图像相同通道数的彩色图像。

  • method:匹配方法,可以是以下之一:

    • cv2.TM_CCOEFF

    • cv2.TM_CCOEFF_NORMED

    • cv2.TM_CCORR

    • cv2.TM_CCORR_NORMED

    • cv2.TM_SQDIFF

    • cv2.TM_SQDIFF_NORMED

    • 这些方法决定了如何度量模板图像与原图像子窗口之间的相似度。

  • 返回值res

    函数在完成图像模板匹配后返回一个结果矩阵,这个矩阵的大小与原图像相同。矩阵的每个元素表示原图像中相应位置与模板图像匹配的相似度。

    匹配方法不同,返回矩阵的值的含义也会有所区别。以下是几种常用的匹配方法及其返回值含义:

    1. cv2.TM_SQDIFFcv2.TM_SQDIFF_NORMED

      返回值越接近0,表示匹配程度越好。最小值对应的最佳匹配位置。

    2. cv2.TM_CCORRcv2.TM_CCORR_NORMED

      返回值越大,表示匹配程度越好。最大值对应的最佳匹配位置。

    3. cv2.TM_CCOEFFcv2.TM_CCOEFF_NORMED

      返回值越大,表示匹配程度越好。最大值对应的最佳匹配位置。

1.2.1 平方差匹配

        cv2.TM_SQDIFF:以模板图与目标图所对应的像素值使用平方差公式来计算,其结果越小,代表匹配程度越高,计算过程举例如下。
        注意:模板匹配过程皆不需要边缘填充,直接从目标图像的左上角开始计算。

1.2.2 归一化平方差匹配

        cv2.TM_SQDIFF_NORMED:与平方差匹配类似,只不过需要将值统一到0到1,计算结果越小,代表匹配程度越高,计算过程举例如下。

1.2.3 相关匹配

        cv2.TM_CCORR:使用对应像素的乘积进行匹配,乘积的结果越大其匹配程度越高,计算过程举例如下。

1.2.4 归一化相关匹配

        cv2.TM_CCORR_NORMED:与相关匹配类似,只不过是将其值统一到0到1之间,值越大,代表匹配程度越高,计算过程举例如下。

1.2.5 相关系数匹配

        cv2.TM_CCOEFF:需要先计算模板与目标图像的均值,然后通过每个像素与均值之间的差的乘积再求和来表示其匹配程度,1表示完美的匹配,-1表示最差的匹配,计算过程举例如下。

1.2.6 归一化相关系数匹配

        cv2.TM_CCOEFF_NORMED:也是将相关系数匹配的结果统一到0到1之间,值越接近1代表匹配程度越高,计算过程举例如下。

1.3 绘制轮廓

        找的目标图像中匹配程度最高的点,我们可以设定一个匹配阈值来筛选出多个匹配程度高的区域。
        loc=np.where(array > 0.8) :loc包含array中所有大于0.8的元素索引的数组;
        zip(*loc)

第1节知识示例:

import cv2 as cv
import numpy as np# x = list([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]])
# print(list(zip(*x)))
game = cv.imread('images/game.png')  # 目标图
temp = cv.imread('images/temp.png')  # 模板图
game_gray = cv.cvtColor(game, cv.COLOR_BGR2GRAY)
temp_gray = cv.cvtColor(temp, cv.COLOR_BGR2GRAY)
# print(game_gray.shape)
# print(temp_gray.shape)# 获取模板图的宽高
shape_t = temp_gray.shape
h, w = shape_t# 模板匹配cv.matchTemplate(目标图,模板图,匹配方法),返回匹配程度的矩阵
res = cv.matchTemplate(game_gray, temp_gray, cv.TM_CCOEFF_NORMED)
# print(res, "---", res.shape)
# 设定阈值
thresh = 0.8
# 找符合条件的值的坐标
loc = np.where(res >= thresh)  # 返回值中,第一个列表中装的是y值,另一个装的是x值;可以理解为坐标值
# print(list(zip(*loc[::-1])))
# print(type(loc))  # tuple# 获取点坐标
for pt in zip(*loc[::-1]):# print(pt)cv.rectangle(game, pt, (pt[0] + w, pt[1] + h), (0, 0, 255), 1)cv.imshow('game', game)
cv.waitKey(0)
cv.destroyAllWindows()

2. 霍夫变换

2.1 理解霍夫变换

        霍夫变换常用来提取图像中的直线和圆等几何形状。

2.2 霍夫直线变换

        对于一条直线(不垂直于x轴的直线),都可以用$y=k x+b$来表示,此时,x和y是横纵坐标,k和b是一个固定参数。当我们换一种方式来看待这个式子,我们就可以得到:

        此时,以k和b    为横纵坐标,x和y为固定参数,变换如下图所示:

        从上图可以看出,在直角坐标系下的一个直线,在变换后的空间中仅仅表示为一点,对于变换后的空间,我们称其为霍夫空间。也就是说,直角坐标系下的一条直线对应了霍夫空间中的一个点。类似的,霍夫空间中的一条直线也对应了直角坐标系中的一个点,如下图所示:

        那么对于一个二值化后的图形来说,其中的每一个目标像素点(这里假设目标像素点为白色像素点)都对应了霍夫空间的一条直线,当霍夫空间中有两条直线相交时,就代表了直角坐标系中某两个点所构成的直线。而当霍夫空间中有很多条线相交于一点时,说明直角坐标系中有很多点能构成一条直线,也就意味着这些点共线,因此我们就可以通过检测霍夫空间中有最多直线相交的交点来找到直角坐标系中的直线。
        然而对于x=1这种直线来说,y已经不存在了,那么就没办法使用上面的方法进行检测了,为了解决这个问题,我们就将直角坐标系转化为极坐标系,然后通过极坐标系与霍夫空间进行相互转化。
 

        在极坐标系下是一样的,极坐标中的点对于霍夫空间中的线,霍夫空间中的点对应极坐标中的直线。并且此时的霍夫空间不再是以k为横轴、b为纵轴,而是以为θ横轴、ρ(上图中的r)为纵轴。上面的公式中,x、y是直线上某点的横纵坐标(直角坐标系下的横纵坐标),和是极坐标下的坐标,因此我们只要知道某点的x和y的坐标,就可以得到一个关于θ-ρ的表达式,如下图所示:

        根据上图,霍夫空间在极坐标系下,一点可以产生一条三角函数曲线,而多条这样的曲线可能会相交于同一点。因此,我们可以通过设定一个阈值,来检测霍夫空间中的三角函数曲线相交的次数。如果一个交点的三角函数曲线相交次数超过阈值,那么这个交点所代表的直线就可能是我们寻找的目标直线。
        使用API:lines=cv2.HoughLines(image, rho, theta, threshold)

  • image:输入图像,通常为二值图像,其中白点表示边缘点,黑点为背景。

  • rho:r的精度,以像素为单位,表示霍夫空间中每一步的距离增量, 值越大,考虑越多的线。

  • theta:角度θ的精度,通常以弧度为单位,表示霍夫空间中每一步的角度增量。值越小,考虑越多的线。

  • threshold:累加数阈值,只有累积投票数超过这个阈值的候选直线才会被返回。

返回值:cv2.HoughLines 函数返回一个二维数组,每一行代表一条直线在霍夫空间中的参数 (rho, theta)
        示例:

import cv2 as cv
import numpy as npimg = cv.imread('images/huofu.png')
shape = img.shape
# 边缘检测
dst = cv.Canny(img, 30, 70)  # 返回值边缘检测后的图像
# cv.imshow('canny', dst)
# 使用霍夫变换检查测直线,返回值是[[rho, theta]],角度单位是弧度
lines = cv.HoughLines(dst, 0.8, np.pi / 180, 90)  # 检测到四条直线
# print(lines)
# 绘制直线
for line in lines:rho, theta = line[0]  # 获取rho(直线到原点的垂直距离)和theta(直线与 x 轴的夹角)sin_theta = np.sin(theta)print(rho, sin_theta)cos_theta = np.cos(theta)x1 = 0y1 = int(rho / sin_theta)print(x1, y1)x2 = shape[1]y2 = int((rho - x2 * cos_theta) / sin_theta)cv.line(img, (x1, y1), (x2, y2), (0, 0, 255), 1)cv.imshow('img', img)
cv.waitKey(0)
cv.destroyAllWindows()

2.3 统计概率霍夫直线变换

        前面的方法又称为**标准霍夫变换**,它会计算图像中的每一个点,计算量比较大,另外它得到的是整一条线(r和θ),并不知道原图中直线的端点。所以提出了**统计概率霍夫直线变换**(Probabilistic Hough Transform),是一种改进的霍夫变换,它在获取到直线之后,会检测原图中在该直线上的点,并获取到两侧的端点坐标,然后通过两个点的坐标来计算该直线的长度,通过直线长度与最短长度阈值的比较来决定该直线要不要被保留。
        使用API:lines=cv2.HoughLinesP(image, rho, theta, threshold, lines=None, minLineLength=0, maxLineGap=0)

  • image:输入图像,通常为二值图像,其中白点表示边缘点,黑点为背景。

  • rho:极径分辨率,以像素为单位,表示极坐标系中的距离分辨率。

  • theta:极角分辨率,以弧度为单位,表示极坐标系中角度的分辨率。

  • threshold:阈值,用于过滤掉弱检测结果,只有累计投票数超过这个阈值的直线才会被返回。

  • lines(可选):一个可初始化的输出数组,用于存储检测到的直线参数。

  • minLineLength(可选):最短长度阈值,比这个长度短的线会被排除。

  • maxLineGap(可选):同一直线两点之间的最大距离。当霍夫变换检测到一系列接近直角的线段时,这些线段可能是同一直线的不同部分。maxLineGap参数指定了在考虑这些线段属于同一直线时,它们之间最大可接受的像素间隔。

    • 如果maxLineGap设置得较小,那么只有相邻且间距很小的线段才会被连接起来,这可能导致检测到的直线数量较多,但更准确地反映了图像中的局部直线结构。

    • 如果maxLineGap设置得较大,则线段间的间距可以更大,这样可能会合并更多的局部线段成为更长的直线,但有可能会将原本不属于同一直线的线段误连接起来。

返回值lines:cv2.HoughLinesP 函数返回一个二维数组,每个元素是一个包含4个元素的数组,分别表示每条直线的起始点和结束点在图像中的坐标(x1, y1, x2, y2)。
        示例:

import cv2 as cv
import numpy as npimg = cv.imread('images/huofu.png')
shape = img.shape
# 边缘检测
dst = cv.Canny(img, 30, 70)  # 返回值边缘检测后的图像
# 统计概率霍夫直线变换
lines = cv.HoughLinesP(dst, 0.8, np.pi / 180, 90, minLineLength=50, maxLineGap=10)
for line in lines:x1, y1, x2, y2 = line[0]cv.line(img, (x1, y1), (x2, y2), (0, 0, 255), 1)cv.imshow('img', img)
cv.waitKey(0)
cv.destroyAllWindows()

2.4 霍夫圆变换

        霍夫圆变换跟直线变换类似,它可以从图像中找出潜在的圆形结构,并返回它们的中心坐标和半径。只不过线是用(r,θ)表示,圆是用(x_center,y_center,r)来表示,从二维变成了三维,数据量变大了很多;所以一般使用霍夫梯度法减少计算量。
        使用API:circles=cv2.HoughCircles(image, method, dp, minDist, param1, param2)

  • image:输入图像,通常是灰度图像。

  • method:使用的霍夫变换方法:霍夫梯度法,可以是 cv2.HOUGH_GRADIENT,这是唯一在OpenCV中用于圆检测的方法。

  • dp:累加器分辨率与输入图像分辨率之间的降采样比率,用于加速运算但不影响准确性。设置为1表示霍夫梯度法中累加器图像的分辨率与原图一致

  • minDist:检测到的圆心之间的最小允许距离,以像素为单位。在霍夫变换检测圆的过程中,可能会检测到许多潜在的圆心。minDist 参数就是为了过滤掉过于接近的圆检测结果,避免检测结果过于密集。当你设置一个较小的 minDist 值时,算法会尝试找出尽可能多的圆,即使是彼此靠得很近的圆也可能都被检测出来。相反,当你设置一个较大的 minDist 值时,算法会倾向于只检测那些彼此间存在一定距离的独立的圆。

    例如,如果你设置 minDist 很小,可能在真实图像中存在的一个大圆旁边的一些噪声点会被误判为多个小圆;而如果设置 minDist 较大,则可以排除这种情况,只保留明显分离的圆的检测结果。

  • param1param2:这两个参数是在使用 cv2.HOUGH_GRADIENT 方法时的特定参数,分别为:

    • param1(可选):阈值1,决定边缘强度的阈值。

    • param2:阈值2,控制圆心识别的精确度。较大的该值会使得检测更严格的圆。param2 通常被称为圆心累积概率的阈值。在使用霍夫梯度方法时,param2 设置的是累加器阈值,它决定了哪些候选圆点集合被认为是有效的圆。较高的 param2 值意味着对圆的检测更严格,只有在累加器中积累了足够高的响应值才认为是真实的圆;较低的 param2 值则会降低检测的门槛,可能会检测到更多潜在的圆,但也可能包含更多的误检结果。

      举个例子,如果你将 param2 设置得较高,那么算法只会返回那些边缘强烈符合圆形特征且周围有足够的支持像素的圆;而如果设置得较低,即使边缘特征不是很强烈,只要有一些证据支持就可能将其视为一个圆。

        返回值:cv2.HoughCircles 返回一个二维numpy数组,包含了所有满足条件的圆的参数。
        示例:

import cv2 as cv
import numpy as npimg = cv.imread('images/huofu.png')
shape = img.shape
# 边缘检测
dst = cv.Canny(img, 30, 70)  # 返回值边缘检测后的图像
# 霍夫圆变换
circles = cv.HoughCircles(dst, cv.HOUGH_GRADIENT, 1, 20, param2=30)
# print(circles)
# 循环、遍历、绘制圆
for circle in circles:x, y, r = circle[:][0].astype(int)# print(x, y, r)cv.circle(img, (x, y), r, (0, 255, 0), 2)cv.imshow('img', img)
cv.waitKey(0)
cv.destroyAllWindows()

3. 图像亮度变换

        我们知道,图像都是由一个个像素值组成的,图像的亮度变换实际上还是图像像素值的变换。

3.1 亮度变换

        在讲解亮度时,需要和对比度一起来进行解释。
        对比度调整:图像暗处像素强度变低,图像亮处像素强度变高,从而拉大中间某个区域范围的显示精度。
        亮度调整:图像像素强度整体变高或者变低。

        上图中:
                (a) 把亮度调高,就是图片中的所有像素值加上了一个固定值;
                (b) 把亮度调低,就是图片中的所有像素值减去了一个固定值;
                (c) 增大像素对比度(白的地方更白,黑的地方更黑);
                (d) 减小像素对比度(整幅图都趋于一个颜色);
        OpenCV调整图像对比度和亮度时,公式为:g(i,j)=\alpha f(i,j)+\beta。但是不能浅显的讲\alpha是控制对比度,\beta是控制亮度的。
        对比度:需要通过\alpha\beta一起控制(仅调整\alpha只能控制像素强度0附近的对比度,而这种做法只会导致像素强度大于0的部分更亮而已,根本看不到对比度提高的效果)。
        亮度:通过\beta控制。

3.2 线性变换

        使用 cv2.addWeighted() 函数,可以对图像的像素值进行加权平均,进而改变图像的整体亮度。亮度增益可以通过向每个像素值添加一个正值来实现。

        cv2.addWeighted(src1, alpha, src2, beta, gamma)

  • src1:第一张输入图像,它将被赋予权重 alpha

  • alpha:第一个输入图像的权重。

  • src2:第二张输入图像,它将被赋予权重 beta

  • beta:第二个输入图像的权重。

  • gamma:一个标量,将被添加到权重求和的结果上,可用于调整总体亮度。

    计算公式为: dst = src1 * alpha + src2 * beta + gamma

        示例:

import cv2 as cv
import numpy as npimg = cv.imread('images/1.jpg')
img2 = np.zeros_like(img)img_n = cv.addWeighted(img, 1.5, img2, 0, 0)
cv.imshow('img', img)
cv.imshow('img_n', img_n)
cv.waitKey(0)
cv.destroyAllWindows()

3.3 直接像素值修改

        如果只需要增加或减少固定的亮度值,可以直接遍历图像像素并对每个像素值进行加减操作。
        使用的API:numpy.clip(a, a_min, a_max)
        
用于对数组中的元素进行限定,将超出指定范围的元素值截断至指定的最小值和最大值之间

  • a:输入数组。

  • a_min:指定的最小值,数组中所有小于 a_min 的元素将被替换为 a_min

  • a_max:指定的最大值,数组中所有大于 a_max 的元素将被替换为 a_max

示例:

import cv2 as cv
import numpy as np# 为滑动条添加窗口
winname = 'Trackbar_win'  # 窗口名
cv.namedWindow(winname)  # 为滑条创建的窗口def change(x):  # x是像素值的变化量# 把值映射到(-255, 255)x = x / 255 * (255 - (-255)) - 255# print(x)  # -55# 读取图像img = cv.imread('images/1.jpg')img_new = np.uint8(np.clip(img + x, 0, 255))  # 原像素值加上一个像素值,变化后的像素值范围是0-255cv.imshow('img', img)cv.imshow('img_new', img_new)maxval = 255  # 滑条最大值
trackval = 100  # 滑条初始值
change(trackval)
# 创建滑条cv.createTrackbar(滑条名, 显示滑条的窗口名, 滑条初始值, 滑条的最大值, 关联函数)
cv.createTrackbar('Trackbar', winname, trackval, maxval, change)
cv.waitKey(0)
cv.destroyAllWindows()

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

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

相关文章

【目标检测】【深度学习】【Pytorch版本】YOLOV3模型算法详解

【目标检测】【深度学习】【Pytorch版本】YOLOV3模型算法详解 文章目录 【目标检测】【深度学习】【Pytorch版本】YOLOV3模型算法详解前言YOLOV3的模型结构YOLOV3模型的基本执行流程YOLOV3模型的网络参数 YOLOV3的核心思想前向传播阶段反向传播阶段 总结 前言 YOLOV3是由华盛顿…

LN2220 2A 高效率升压 DC/DC 电压调整器

1、产品概述 LN2220 是一款微小型、高效率、升压型 DC/DC 调整器。 电路由电流模 PWM 控制环路,误差放大器,斜波补偿电路, 比较器和功率开关等模块组成。该芯片可在较宽负载范围内 高效稳定的工作,内置一个 4A 的功率开关和…

【大模型基础_毛玉仁】6.3 知识检索

目录 6.3 知识检索6.3.1 知识库构建1)数据采集及预处理2)知识库增强 6.3.2 查询增强1)查询语义增强2)查询内容增强 6.3.3 检索器1)判别式检索器2)生成式检索器 6.3.4 检索效率增强1)相似度索引算…

静态方法和实例方法

在 Java 中,‌静态方法(static method)‌和‌实例方法(instance method)‌是两种不同类型的方法,它们在调用方式、内存分配和访问权限上有显著区别。以下是详细对比: ‌1. 静态方法(…

Lua环境搭建+Lua基本语法

前期准备: 搜索并下载安装LuaForWindows,例: 安装完成后开启cmd窗口,输入lua 出现版本号证明成功下载安装 使用Sublime Text编辑器编写Lua 使用浏览器或CSDN搜索Sublime Text下载并安装,安装成功后打开编辑器,编辑…

FFmpeg录制屏幕和音频

一、FFmpeg命令行实现录制屏幕和音频 1、Windows 示例 #include <cstdlib> #include <string> #include <iostream>int main() {// FFmpeg 命令行&#xff08;录制屏幕 麦克风音频&#xff09;std::string command "ffmpeg -f gdigrab -framerate 3…

【数据集】多视图文本数据集

多视图文本数据集指的是包含多个不同类型或来源的信息的文本数据集。不同视图可以来源于不同的数据模式&#xff08;如原始文本、元数据、网络结构等&#xff09;&#xff0c;或者不同的文本表示方法&#xff08;如 TF-IDF、词嵌入、主题分布等&#xff09;。这些数据集常用于多…

C++ 继承方式使用场景(极简版)

1. 公有继承&#xff08;public&#xff09; 什么时候用&#xff1f; “是一个”&#xff08;is-a&#xff09;关系&#xff1a;派生类 是 基类的一种。 例&#xff1a;class Dog : public Animal&#xff08;狗是动物&#xff09; 最常见&#xff0c;90%的继承都用它。 2. 保…

Ubuntu 系统 Docker 中搭建 CUDA cuDNN 开发环境

CUDA 是 NVIDIA 推出的并行计算平台和编程模型&#xff0c;利用 GPU 多核心架构加速计算任务&#xff0c;广泛应用于深度学习、科学计算等领域。cuDNN 是基于 CUDA 的深度神经网络加速库&#xff0c;为深度学习框架提供高效卷积、池化等操作的优化实现&#xff0c;提升模型训练…

高密度任务下的挑战与破局:数字样机助力火箭发射提效提质

2025年4月1日12时&#xff0c;在酒泉卫星发射中心&#xff0c;长征二号丁运载火箭顺利升空&#xff0c;成功将一颗卫星互联网技术试验卫星送入预定轨道&#xff0c;发射任务圆满完成。这是长征二号丁火箭的第97次发射&#xff0c;也是长征系列火箭的第567次发射。 执行本次任务…

关于SQL子查询的使用策略

在 SQL 优化中&#xff0c;一般遵循**“非必要不使用子查询”**的原则&#xff0c;因为子查询可能会带来额外的计算开销&#xff0c;影响查询效率。但是&#xff0c;并不是所有子查询都需要避免&#xff0c;有时子查询是最优解&#xff0c;具体要根据实际场景选择合适的优化方式…

JavaEE初阶复习(JVM篇)

JVM Java虚拟机 jdk java开发工具包 jre java运行时环境 jvm java虚拟机(解释执行 java 字节码) java作为一个半解释,半编译的语言,可以做到跨平台. java 通过javac把.java文件>.class文件(字节码文件) 字节码文件, 包含的就是java字节码, jvm把字节码进行翻译转化为…

2.pycharm保姆级安装教程

一、pycharm安装 1.官网上下载好好软&#xff0c;双击打开 2.下一步 3.修改路径地址 (默认也可以) 4.打勾 5.安装 不用重启电脑 二、添加解释器 1.双击软件&#xff0c;打开 2.projects – new project 3.指定项目名字&#xff0c;项目保存地址&#xff0c;解释器 4.右击 – …

zk基础—4.zk实现分布式功能二

大纲 1.zk实现数据发布订阅 2.zk实现负载均衡 3.zk实现分布式命名服务 4.zk实现分布式协调(Master-Worker协同) 5.zk实现分布式通信 6.zk实现Master选举 7.zk实现分布式锁 8.zk实现分布式队列和分布式屏障 4.zk实现分布式协调(Master-Worker协同) (1)Master-Worker架构…

Java 实现 字母异位词分组

在这篇博客中&#xff0c;我们将详细解析如何使用 Java 代码来解决 字母异位词分组这个经典的算法问题。我们会逐步分析代码逻辑&#xff0c;并探讨其时间复杂度及优化思路。 题目描述 给定一个字符串数组 strs&#xff0c;请将字母异位词组合在一起。字母异位词是指由相同字…

【Ragflow】10. 助理配置参数详细解析/模型响应加速方法

概述 Ragflow的助理配置中&#xff0c;有很多参数&#xff0c;尽管官方文档给出了一定程度的解释&#xff0c;但不够详细。 本文将对各项参数进行更详细的解释说明&#xff0c;并进一步挖掘某些参数中隐含的潜在陷阱。 助理设置 空回复 含义&#xff1a;输入的问题若未能在…

Mac Apple silicon如何指定运行amd64架构的ubuntu Docker?

如何指定运行amd64架构的ubuntu Docker 下面这个docker命令如何指定运行amd64架构的ubuntu Docker&#xff1f; docker run -it -v $(pwd):/workspace ubuntu:20.04 bash这个命令已经非常接近正确运行一个基于 amd64 架构的 Ubuntu 容器了&#xff0c;但如果你想明确指定运行…

ColPali:基于视觉语言模型的高效文档检索

摘要 文档是视觉丰富的结构&#xff0c;不仅通过文本传递信息&#xff0c;还包括图表、页面布局、表格&#xff0c;甚至字体。然而&#xff0c;由于现代检索系统主要依赖从文档页面中提取的文本信息来索引文档&#xff08;通常是冗长且脆弱的流程&#xff09;&#xff0c;它们…

使用C++实现HTTP服务

天天开心&#xff01;&#xff01;&#xff01; 阅读本篇文章之前&#xff0c;请先阅读HTTP基础知识 传送门----> HTTP基础知识 文章目录 一、CWeb服务器&#xff08;核心代码WebServer.cpp&#xff09;二、静态文件结构三、编译和运行四、访问测试 一、CWeb服务器&#xff…

Reactive编程入门:Project Reactor 深度指南

文章目录 4.2.1 创建 Flux 和 MonoFlux 基础创建方式高级创建模式Mono 创建方式 4.2.2 订阅与数据处理基础订阅模式数据处理操作符 4.2.3 核心操作符深度解析flatMap 操作符zip 操作符buffer 操作符 高级组合模式复杂流处理示例背压处理策略 测试响应式流性能优化技巧 React 编…