OpenCV——直方图与匹配

直方图与匹配

  • 一、直方图简介
  • 二、直方图统计
  • 三、直方图比较
  • 四、直方图均衡化
  • 五、自适应的直方图均衡化
  • 六、直方图反向投影
  • 七、模板匹配

一、直方图简介

图像直方图(Histogram)是一种频率分布图,它描述了不同强度值在图像中出现的频率。图像直方图可以统计任何图像特征,如灰度、饱和度、梯度等。

彩色图像的亮度直方图就是其灰度图的直方图。亮度直方图考虑了所有颜色通道,但有时也需要对单种颜色通道进行观察分析。计算单种颜色通道直方图时,每种颜色通道都作为一个独立的灰度图像,分别计算其直方图。各种颜色通道的直方图有时近似的,有时则相差甚远,特别是当图像偏于某一色系时。

在讨论直方图时经常涉及以下3个概念:

  1. Dims(维数):需要统计的特征的维数,一般情况下,图像直方图统计的特征只有一种,即灰度,此时的维数等于1。
  2. Bins(组距):每个特征空间子区段的数目
  3. Range(范围):需要统计的特征的取值范围。通常情况下,图像直方图的灰度范围为[0, 255]

下面用一个示例说明直方图的画法。假设有一副8*8的图像,其灰度数据如下,为了简化起见,将灰度区段数(Bins)设为16,编号为b0~b15,具体如下:

[0, 255] = [0, 15] U [16, 31] U...U [240, 255];
其中b0==[0,15],b1=[16,31],...,b15=[240,255]
//灰度值的取值范围为[0, 255]

灰度值数据

381301671912151803318
154165391066218524
243252622139454683
1392204111118920483
11918860241154196244169
441001720428185166196
1631001720428185166196
2264220558728166146

第一步,将灰度值转换为Bin的编号,方法是将灰度值除以16,然后舍弃小数部分,如38除以16等于2,130除以16等于8等,转换后的数据如下:

281011131121
9102040111
15153135340
80126011125
7113159121510
211462121112
1061121111012
14013351109

第二步,统计16个灰度范围(Bin的编号)的个数,如下表

Bin0123456789101112131415合计
个数665423312367732464

第三步,根据上表,画出直方图如下,x轴代表一个灰度范围,y轴代表个数:
在这里插入图片描述

由于直方图只统计数量而不考虑像素在图像中的位置,因而具有平移性、旋转和缩放不变性。也正是因为这个原因,两幅截然不同不同的图像的直方图可能是一样的。

通过对直方图的分析,可以发现有关亮度(曝光)和对比度的问题,并可以了解一张图像是否有效利用了整个强度范围。直方图的均值和中值可用来描述图像的亮度,其中中值比均值更具稳健性:直方图的标准差(或方差)则可以用来描述图像的对比度。

由于直方图中数字越大亮度也越大,因此直方图中的柱形明显击中于中间和右侧,左侧靠近0(黑色)的位置则非常稀疏,这说明这张图像整体偏亮。直方图的峰值都集中在左侧的图像往往曝光不足,而击中在右侧的图像则往往曝光过度。对比度的高低在直方图上也是一目了然的。如果图像的大部分像素集中在直方图的某个范围,则说明其对比度较低,如果像素扩展至直方图整个范围,则对比度较高。

二、直方图统计

在OpenCV中绘制直方图需要先进行直方图统计,然后用绘图函数把直方图绘制出来。

//图像直方图的数据统计
void Imgproc.calcHist(List<Mat> images, MatOfint channels, Mat mask, Mat hist, MatOfInt histSize, MatOfFloat ranges)
  • image:输入图像
  • channels:需要统计直方图的第几通道:如输入图像是灰度图,则它的值是0,如是彩色图像,则用0、1、2代表B、G、R三个通道
  • mask:掩膜,如是整幅图像的直方图,则无须定义
  • hist:直方图计算结束
  • histSize:直方图被分成多少个取件,即bin的个数
  • ranges:像素取值范围,通常为0-255

上述函数只负责统计数据,如果想要看到直方图,则还需要用绘图函数把直方图画出来,但是这里有一个小问题。直方图统计出来的是灰度值范围的个数,有的值可能很大,有的则可能很小,要在一张图像中把它们画出来需要先统计出这些值的最大值,然后根据比例画出来。这样相当繁琐,而用OpenCV中的normalize()函数进行归一化就可以解决这个问题。

//对矩阵进行归一化
void Core.normalize(Mat src, Mat dst, double alpha, double beta, int norm_type)
  • src:输入图像
  • dst:输出矩阵,与src具有同样的尺寸
  • alpha:归一化后的上限值
  • beta:归一化后的上限值
  • norm_type:归一化类型,常用参数如下:
    • Core.NORM_INF:无穷范数,向量最大值
    • Core.NORM_L1:L1范数,绝对值之和
    • Core.NORM_L2:L2范数,平方和之平方根
    • Core.NORM_L2SQR:L2范数,平方和
    • Core.NORM_MINMAX:偏移归一化
public class CalcHist {static {OpenCV.loadLocally(); // 自动下载并加载本地库}public static void main(String[] args) {//读取图像灰度图并显示Mat src = Imgcodecs.imread("/Users/acton_zhang/J2EE/MavenWorkSpace/opencv_demo/src/main/java/demo1/key.jpg", Imgcodecs.IMREAD_GRAYSCALE);HighGui.imshow("src", src);HighGui.waitKey(0);//参数准备List<Mat> mat = new ArrayList<>();mat.add(src);float[] range = {0, 256};//直方图统计值范围Mat hist = new Mat();MatOfFloat histRange = new MatOfFloat(range);//直方图数据统计并归一化Imgproc.calcHist(mat, new MatOfInt(0), new Mat(), hist, new MatOfInt(256), histRange);//直方图尺寸int width = 512;int height = 400;Core.normalize(hist, hist, 0, height, Core.NORM_MINMAX);//将直方图数据转存到数组中以便后续使用float[] histData = new float[(int)(hist.total() * hist.channels())];hist.get(0, 0, histData);//绘制直方图Scalar black = new Scalar(0, 0, 0);Scalar white = new Scalar(255, 255, 255);Mat histImage = new Mat(height, width, CvType.CV_8UC3, black);int binWid = (int)Math.round((double)width / 256);//bin的宽度for (int i = 0; i < 256; i++) {Imgproc.line(histImage, new Point(i * binWid, height), new Point(i * binWid, height - Math.round(histData[i])), white, binWid);}//在屏幕上显示绘制的直方图HighGui.imshow("calcHist", histImage);HighGui.waitKey(0);System.exit(0);}
}

原图:
在这里插入图片描述

直方图:

在这里插入图片描述

三、直方图比较

由于直方图反映了图像的灰度值的分布特性,因而通过直方图的比较可以在一定程度上了解两幅图像的相似程度。当然,由于两幅截然不同的图像的直方图可能是完全一样的,这种比较只能作为参考。

//比较两幅直方图。此函数适用于一维、二维、三维密集直方图,但可能不适用于高维稀疏直方图
double Imgproc.compareHist(Mat h1, Mat h2, int method)
  • h1:第一个直方图
  • h2:第二个直方图
  • method:比较方法,如下:

在这里插入图片描述

public class CompareHist {static {OpenCV.loadLocally(); // 自动下载并加载本地库}public static void main(String[] args) {//读取图像灰度图并显示Mat src = Imgcodecs.imread("/Users/acton_zhang/J2EE/MavenWorkSpace/opencv_demo/src/main/java/demo1/pond.png", Imgcodecs.IMREAD_GRAYSCALE);HighGui.imshow("src", src);HighGui.waitKey(0);//对图像进行中值滤波并显示Mat src2 = new Mat();Imgproc.medianBlur(src, src2, 5);HighGui.imshow("Median Blur", src2);HighGui.waitKey(0);//直方图参数设置float[] range = {0, 256};MatOfFloat histRange = new MatOfFloat(range);//图像1的直方图数据统计并归一化Mat hist = new Mat();List<Mat> matList = new LinkedList<>();matList.add(src);Imgproc.calcHist(matList, new MatOfInt(0), new Mat(), hist, new MatOfInt(256), histRange);Core.normalize(hist, hist, 0, 400, Core.NORM_MINMAX);//图像2的直方图数据统计并归一化Mat hist2 = new Mat();List<Mat> matList2 = new LinkedList<>();matList2.add(src2);Imgproc.calcHist(matList2, new MatOfInt(0), new Mat(), hist2, new MatOfInt(256), histRange);Core.normalize(hist2, hist2, 0, 400, Core.NORM_MINMAX);double s = Imgproc.compareHist(hist, hist2, Imgproc.HISTCMP_CORREL);System.out.println("相似度:" + s);System.exit(0);}
}
相似度:0.9987133134938458

程序中用于比较两幅图像中一幅是未处理的原图像。另一幅是经过中值滤波后的图像。经过比较两者相似度约为0.9987。由于比较方法用的是相关性比较,完全一致时相似度为1,此结果显示两者相似度非常高。

当然,如前所述,直方图只统计数量而不考虑像素在图像中的位置,因而两幅截然不同的图像的直方图可能是一样的。直方图的比较结果完全匹配也并不能说明两幅图像是一样的,但如果两幅图像完全一样,则它们的直方图必然是完全匹配的。

四、直方图均衡化

在曝光不足或曝光过度时,直方图往往集中在一个区域,而解决问题的方法就是直方图均衡化。所谓直方图均衡化,就是尽可能地让一张图像的像素占据全部可能的灰度级并且分布均匀,从而具有较高的对比度。直方图均衡化的原理图如下:

在这里插入图片描述

//对图像进行直方图均衡化
void Imgproc.equalizeHist(Mat src, Mat dst)
  • src:输入图像,必须是8位单通道图像
  • dst:输出图像,和src具有相同的尺寸和数据类型
public class EqualizeHist {static {OpenCV.loadLocally(); // 自动下载并加载本地库}public static void main(String[] args) {//读取图像灰度图并显示Mat src = Imgcodecs.imread("/Users/acton_zhang/J2EE/MavenWorkSpace/opencv_demo/src/main/java/demo1/grotto.jpg", Imgcodecs.IMREAD_GRAYSCALE);HighGui.imshow("src", src);HighGui.waitKey(0);//直方图均衡化并在屏幕上显示结果Mat dst = new Mat();Imgproc.equalizeHist(src, dst);HighGui.imshow("dst", dst);HighGui.waitKey(0);System.exit(0);}
}

原图:

在这里插入图片描述

直方图均衡化:

在这里插入图片描述

五、自适应的直方图均衡化

直方图均衡对于背景和前景都太亮或太暗的图像很有效,但是在很多情况下其效果并不理想。直方图均衡化主要存在以下两个问题:

  1. 某些区域由于对比度增强过大而成为噪点
  2. 某些区域调整后变得更暗或更亮,从而丢失细节

针对上述两个问题,先后有人提出了对比度限制直方图均衡算法(CLHE算法)和自适应直方图均衡算法(AHE算法)。

CLHE算法在HE算法的基础上加入了对比度限制,算法中设置了一个直方图分布的阈值,将超过该阈值的部分均匀地分散到其他Bins中,其原理如下:
在这里插入图片描述
AHE算法则将图像分成很多小块,对每个小块进行直方图均衡化,然后将这些小块拼接起来,但是这样又产生了新的问题,由于对每个小块进行均衡化时的参数不同,小块之间会产生一些边界。

限制对比度自适应直方图均衡化(CLAHE算法)综合了这两个算法的优点,并通过双线性差值的方法对小块进行缝合以消除边界问题。严格的说,自适应的直方图均衡化算法是指AHE算法,而不是CLAHE算法。不过,为了简化起见,目前在提起 自适应的直方图均衡化算法 时所指的基本是CLAHE算法。

为了实现这个算法,OpenCV中专门设置了CLAHE类。CLAHE算法的实现一般需要如下两步:
1. 创建一个CLAHE类:

CLAHE clahe = Imgproc.createCLAHE();

2. 调用CLAHE.apply()函数进行自适应的直方图均衡化:

clahe.apply(src, dst);
public class Clahe {static {OpenCV.loadLocally(); // 自动下载并加载本地库}public static void main(String[] args) {//读取图像灰度图并显示Mat src = Imgcodecs.imread("F:/IDEAworkspace/opencv/src/main/java/demo2/grotto.jpg", Imgcodecs.IMREAD_GRAYSCALE);HighGui.imshow("src", src);HighGui.waitKey(0);//直方图均衡化并显示结果Mat dst = new Mat();Imgproc.equalizeHist(src, dst);HighGui.imshow("dst", dst);HighGui.waitKey(0);//自适应直方图均衡化并显示CLAHE clahe = Imgproc.createCLAHE();clahe.apply(src, dst);HighGui.imshow("CLAHE", dst);HighGui.waitKey(0);System.exit(0);}
}

原图:
在这里插入图片描述

直方图均衡化:
在这里插入图片描述

自适应直方图均衡化:

在这里插入图片描述
总体来看,直方图均衡化后的图像黑白对比仍然强烈,佛像背后有一块黑色阴影,细节根本看不到,另外佛像下方底座部分仍然曝光过度。自适应的直方图均衡化后的图像总体对比度降低、因而细节展现更多。得益于分块均衡化的算法,佛像背后的阴影部分没有那么黑了,因而可以看到一些细节;另外佛像下方曝光过度问题也大有改善,但是左上角出现了明显的块状,这是原图中没有的,这就是CLAHE算法在分块均衡化后缝合效果不理想的表现,也可以说是这个算法的一个副作用。

六、直方图反向投影

直方图反向投影是指先计算某一特征的直方图模型,然后使用该模型去寻找图像中是否存在该特征。反向投影可用于检测输入图像在给定图像中最匹配的区域,因而常用于目标追踪的MeanShift算法配合使用。

//对图像直方图进行反向投影
void Imgproc.calcBackProject(List<Mat> images, MatOfInt channels, Mat hist, Mat dst, MatOfFloat ranges, double scale)
  • images:输入的图像集,所有图像应具有相同的尺寸和数据类型,但通道数可以不同,图像深度应为CV_8U、CV_16U或CV_32F
  • channels:需要统计的通道索引
  • hist:输入的直方图
  • dst:输出的反向投影图像
  • ranges:直方图中bin的取值范围
  • scale:输出的反向投影的缩放因子
public class BackProject {static {OpenCV.loadLocally(); // 自动下载并加载本地库}public static void main(String[] args) {//读取图像转换为HSV色彩空间并显示Mat src = Imgcodecs.imread("F:/IDEAworkspace/opencv/src/main/java/demo/leaf.png");Mat hsv = new Mat();Imgproc.cvtColor(src, hsv, Imgproc.COLOR_BGR2HSV);HighGui.imshow("leaf", hsv);HighGui.waitKey(0);//将图像的hue(色调)通道提取至hueList中Mat hue = new Mat(hsv.size(), hsv.depth());List<Mat> hsvList = new LinkedList<>();List<Mat> hueList = new LinkedList<>();hsvList.add(hsv);hueList.add(hue);Core.mixChannels(hsvList, hueList, new MatOfInt(0, 0));//直方图参数设置int bins = 25;int histSize = Math.max(bins, 2);float[] hueRange = {0, 180};//直方图数据统计并归一化Mat hist = new Mat();Imgproc.calcHist(hueList, new MatOfInt(0), new Mat(), hist, new MatOfInt(histSize), new MatOfFloat(hueRange));Core.normalize(hist, hist, 0, 255, Core.NORM_MINMAX);//计算反向投影并显示Mat backproj = new Mat();Imgproc.calcBackProject(hueList, new MatOfInt(0), hist, backproj, new MatOfFloat(hueRange), 1);HighGui.imshow("calcHist", backproj);HighGui.waitKey(0);System.exit(0);}
}

原图HSV:
在这里插入图片描述

反向投影:
在这里插入图片描述

七、模板匹配

直方图反向投影可用于检测输入图像在给定图像中最匹配的区域,但是由于直方图的局限性,直方图反向投影得到的匹配结果只能作为参考,如果需要精确匹配,则还需要用到模板匹配。

模板匹配是指在一张图像中寻找与另一幅模板图像最佳匹配(相似)区域。所谓模板,就是用来对比的图像。模板匹配的具体方法是:在待匹配图像中选择与模板相同尺寸的滑动窗口,然后不断地移动滑动窗口,计算其与图像中相应区域的匹配度,最终匹配度最高的区域即为匹配结果。

//在图像中寻找与模板匹配的区域
void Imgproc.matchTemplate(Mat image, Mat temp1, Mat result, int method)
  • image:待匹配图像,要求是8位或32位浮点图像
  • temp1:模板图像,其数据类型与待匹配图像相同,并且尺寸不能大于待匹配图像
  • result:输出的匹配图,必须是32位浮点图像。如果待匹配图像的尺寸为WH,模板图像尺寸为wh,则输出图像尺寸为(W-w+1)*(H-h+1)
  • method:匹配方法,可选参数如下,相应计算公式如下表
    • Imgproc.TM_SQDIFF:平方差匹配法。完全匹配时计算值为0,匹配度越低数值越大
    • Imgproc.TM_SQDIFF_NORMED:归一化平方差匹配法。将平方差匹配法归一化到0~1
    • Imgproc.TM_CCORR:相关匹配法。0为最差匹配,数值越大匹配效果越好
    • Imgproc.TM_CCORR_NORMED:归一化相关匹配法。将相关匹配法归一化到0~1
    • Imgproc.TM_CCOEFF:系数匹配法。数值越大匹配度越高,数值越小匹配度越低
    • Imgproc.TM_CCOEFF_NORMED:归一化系数匹配法。将系数匹配法归一化到-1~1,1表示完全匹配,-1表示完全不匹配

由于matchTemplate()函数只是计算各个区域的匹配度,要得到最佳匹配还需要用minMaxLoc()函数来定位:

//寻找矩阵中的最大值和最小值及在矩阵中的位置
MinMaxLocResult Core.minMaxLoc(Mat src)
  • src:输入矩阵,必须是单通道

在这里插入图片描述

public class MatchTemplate {static {OpenCV.loadLocally(); // 自动下载并加载本地库}public static void main(String[] args) {//读取图像并显示Mat src = Imgcodecs.imread("/Users/acton_zhang/J2EE/MavenWorkSpace/opencv_demo/src/main/java/demo1/fish.png");HighGui.imshow("src", src);HighGui.waitKey(0);//读取模板图像并显示Mat template = Imgcodecs.imread("/Users/acton_zhang/J2EE/MavenWorkSpace/opencv_demo/src/main/java/demo1/leaf.png");HighGui.imshow("template", template);HighGui.waitKey(0);//进行模板匹配:结果在result中Mat result = new Mat();Imgproc.matchTemplate(src, template, result, Imgproc.TM_CCOEFF);//取出最大值的位置(TM_CCOEFF模式用最大值)Core.MinMaxLocResult mmr = Core.minMaxLoc(result);Point pt = mmr.maxLoc;//用矩形画出匹配位置并在屏幕上显示Scalar red = new Scalar(0, 0, 255);Imgproc.rectangle(src, pt, new Point(pt.x + template.cols(), pt.y + template.rows()), red, 3);HighGui.imshow("match", src);HighGui.waitKey(0);System.exit(0);}
}

原图:

在这里插入图片描述

模板:
在这里插入图片描述

匹配结构:

在这里插入图片描述

上述程序只能找到最佳匹配,而有时匹配的图像不止一个,此时就要从matchTemplate()函数的结构中找出所有符合条件的图像。下面用一个完整的程序说明如何将模板匹配运用于多目标匹配:

public class MatchTemplate2 {static {OpenCV.loadLocally(); // 自动下载并加载本地库}public static void main(String[] args) {//读取图像并显示Mat src = Imgcodecs.imread("/Users/acton_zhang/J2EE/MavenWorkSpace/opencv_demo/src/main/java/demo2/rose.png");HighGui.imshow("src", src);HighGui.waitKey(0);//读取模板图像并显示Mat template = Imgcodecs.imread("/Users/acton_zhang/J2EE/MavenWorkSpace/opencv_demo/src/main/java/demo2/my.png");HighGui.imshow("template", template);HighGui.waitKey(0);//进行模板匹配,匹配值范围为-1~1Mat result = new Mat();Imgproc.matchTemplate(src, template, result, Imgproc.TM_CCOEFF_NORMED);System.out.println(result);//参数准备float[] p = new float[3];Scalar red = new Scalar(0, 0, 255);int temprow = template.rows();int tempcol = template.cols();//搜索匹配值>0.8的像素for (int i = 0; i < result.rows(); i++) {for (int j = 0; j < result.cols(); j++) {//获取像素的匹配值result.get(i, j, p);//匹配值>0.8的像素用矩形画出if (p[0] > 0.8) {Imgproc.rectangle(src, new Point(j, i), new Point(j + tempcol, i + temprow), red, 3);}}}//显示匹配结果HighGui.imshow("match", src);HighGui.waitKey(0);System.exit(0);}
}

原图:

在这里插入图片描述

模板:

在这里插入图片描述

匹配结果:

在这里插入图片描述

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

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

相关文章

通义大模型在文档自动化处理中的高效部署指南(OCR集成与批量处理优化)

1. 传统OCR解决方案常面临识别精度低、版面分析能力弱、处理效率瓶颈等问题。通义大模型凭借其多模态理解和生成能力&#xff0c;为文档处理领域带来革命性突破。本文将深入探讨如何高效部署通义大模型实现端到端的文档自动化处理&#xff0c;特别聚焦OCR集成与批量处理优化两…

Ubuntu20.04通过ssh协议配置远程终端

一、在目标计算机&#xff08;即被连接的计算机&#xff09;上操作&#xff1a; 1、安装 OpenSSH 服务器&#xff1a; sudo apt update sudo apt install openssh-server3、启动并设置 SSH 服务开机自启&#xff1a; sudo systemctl enable --now ssh二、在源计算机&#xf…

《HTTP权威指南》 第7章 缓存

带着问题学习&#xff1a; 缓存如何提高性能如何衡量缓存的有效性缓存置于何处作用最大HTTP如何保持缓存副本的新鲜度缓存如何与其他缓存及服务器通信 web缓存是可以自动保存常见文档副本的HTTP设备。 缓存优点 减少冗余的数据传输&#xff0c;节省网络费用缓解网络瓶颈问题&…

第十三章 模板

函数模板 函数模板使用 函数模板注意事项 自动类型推导&#xff0c;必须推导出一致的数据类型T,才可以使用 模板必须要确定出T的数据类型&#xff0c;才可以使用 普通函数和函数模板的类型转化 普通函数隐式类型转化&#xff08;char转int&#xff09; 函数模板正常使用不会发生…

云计算-专有网络VPC

&#x1f310; 什么是 VPC&#xff1f;&#xff08;Virtual Private Cloud&#xff09; VPC&#xff08;Virtual Private Cloud&#xff0c;虚拟私有云&#xff09; 是公有云服务商提供的一种网络隔离服务&#xff0c;允许用户在云中创建一个逻辑隔离的私有网络环境。你可以在这…

关于*gin.Context的理解

关于*gin.Context的理解 作为初学者&#xff0c;在学习go语言用gin开发web时&#xff0c;我对*gin.Context感到困惑。本文章以自我总结为主&#xff0c;大部分为来自询问ai后的总结&#xff0c;如有问题欢迎指出。 *gin.Context可以理解为一个gin框架的上下文对象指针&#x…

Qt中的OpenGL (6)[坐标系统]

文章目录 文章说明学习目标目录结构坐标系统局部空间世界空间观察空间裁剪空间正射投影矩阵透视投影矩阵组合进入3D世界顶点数据着色器设置数据矩阵设置文章说明 本文是学习OpenGL的笔记,主要参考大神JoeyDeVries的LearnOpenGL第八课《坐标系统》,并将教程中的代码基于Qt进行…

Spring Aop @After (后置通知)的使用场景?

核心定义 After 是 Spring AOP 中的另一种通知&#xff08;Advice&#xff09;类型&#xff0c;通常被称为“后置通知”或“最终通知”。 它的核心作用是&#xff1a; 无论目标方法是正常执行完成&#xff0c;还是在执行过程中抛出了异常&#xff0c;After 通知中的代码 总是…

UNet改进(4):交叉注意力(Cross Attention)-多模态/多特征交互

在计算机视觉领域&#xff0c;UNet因其优异的性能在图像分割任务中广受欢迎。本文将介绍一种改进的UNet架构——UNetWithCrossAttention&#xff0c;它通过引入交叉注意力机制来增强模型的特征融合能力。 1. 交叉注意力机制 交叉注意力(Cross Attention)是一种让模型能够动态地…

C#里从CSV文件加载BLOB数据字段到数据库的处理

大量的数据保存在CSV文件, 当需要把这些数据加载到数据库,然后使用数据库来共享出去。 就需要把CSV文件导入数据库, 怎么样快速地把CSV文件导入数据库呢? 这个就需要使用类MySqlBulkLoader,它是mariadb数据库快速导入的方式。 一般使用SQL语句导入是10秒,那么使用这种方…

【后端】负载均衡

长期不定期更新补充。 定义 负载均衡&#xff08;Load Balancing&#xff09;是指将来自客户端的请求合理分发到多个服务器或服务节点&#xff0c;以提高系统性能、可用性与可靠性。 分工 前端不做负载均衡&#xff0c;前端只发请求&#xff0c;不知道请求去哪台服务器。 负…

记录一次:Java Web 项目 CSS 样式/图片丢失问题:一次深度排查与根源分析

记录一次&#xff1a;Java Web 项目 CSS 样式/图片丢失问题&#xff1a;一次深度排查与根源分析 **记录一次&#xff1a;Java Web 项目 CSS 样式丢失问题&#xff1a;一次深度排查与根源分析****第一层分析&#xff1a;资源路径问题****第二层分析&#xff1a;服务端跳转逻辑**…

torchmd-net开源程序是训练神经网络潜力

​一、软件介绍 文末提供程序和源码下载 TorchMD-NET 提供最先进的神经网络电位 &#xff08;NNP&#xff09; 和训练它们的机制。如果有多个 NNP&#xff0c;它可提供高效、快速的实现&#xff0c;并且它集成在 GPU 加速的分子动力学代码中&#xff0c;如 ACEMD、OpenMM 和 …

在Docker上安装Mongo及Redis-NOSQL数据库

应用环境 Ubuntu 20.04.6 LTS (GNU/Linux 5.15.0-139-generic x86_64) Docker version 28.1.1, build 4eba377 文章目录 一、部署Mongo1. 拉取容器镜像2. 生成Run脚本2.1 准备条件2.2 参数解读2.3 实例脚本 3. 实例操作3.1 Mongo bash控制台3.2 库表操作 4. MongoDB Compass (G…

Java 编程之责任链模式

一、什么是责任链模式&#xff1f; 责任链模式&#xff08;Chain of Responsibility Pattern&#xff09; 是一种行为型设计模式&#xff0c;它让多个对象都有机会处理请求&#xff0c;从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链&#xff0c;沿着这条…

1、做中学 | 一年级上期 Golang简介和安装环境

一、什么是golang Golang&#xff0c;通常简称 Go&#xff0c;是由 Google 公司的 Robert Griesemer、Rob Pike 和 Ken Thompson 于 2007 年创建的一种开源编程语言&#xff0c;并在 2009 年正式对外公布。 已经有了很多编程语言&#xff0c;为什么还要创建一种新的编程语言&…

Linux--迷宫探秘:从路径解析到存储哲学

上一篇博客我们说完了文件系统在硬件层面的意义&#xff0c;今天我们来说说文件系统在软件层是怎么管理的。 Linux--深入EXT2文件系统&#xff1a;数据是如何被组织、存储与访问的&#xff1f;-CSDN博客 &#x1f30c; 引言&#xff1a;文件系统的宇宙观 "在Linux的宇宙中…

淘宝商品数据实时获取方案|API 接口开发与安全接入

在电商数据获取领域&#xff0c;除了官方 API&#xff0c;第三方数据 API 接入也是高效获取淘宝商品数据的重要途径。第三方数据 API 凭借丰富的功能、灵活的服务&#xff0c;为企业和开发者提供了多样化的数据解决方案。本文将聚焦第三方数据 API 接入&#xff0c;详细介绍其优…

什么是防抖和节流?它们有什么区别?

文章目录 一、防抖&#xff08;Debounce&#xff09;1.1 什么是防抖&#xff1f;1.2 防抖的实现 二、节流&#xff08;Throttle&#xff09;2.1 什么是节流&#xff1f;2.2 节流的实现方式 三、防抖与节流的对比四、总结 在前端开发中&#xff0c;我们经常会遇到一些高频触发的…

Springboot集成阿里云OSS上传

Springboot集成阿里云OSS上传 API 接口描述 DEMO提供的四个API接口&#xff0c;支持不同方式的文件和 JSON 数据上传&#xff1a; 1. 普通文件上传接口 上传任意类型的文件 2. JSON 字符串上传接口 上传 JSON 字符串 3. 单个 JSON 压缩上传接口 上传并压缩 JSON 字符串…