当前位置: 首页 > news >正文

Android 图片相识度比较(pHash)

概述

在 Android 中,要比对两张 Bitmap 图片的相似度,常见的方法有基于像素差异直方图比较、或者使用一些更高级的算法如 SSIM(结构相似性)感知哈希(pHash)

1. 基于像素的差异比较

可以逐像素比较两张 Bitmap,计算它们之间的差异。以下是一个简单的逐像素比较的例子:

public static double compareBitmaps(Bitmap bitmap1, Bitmap bitmap2) {if (bitmap1.getWidth() != bitmap2.getWidth() || bitmap1.getHeight() != bitmap2.getHeight()) {throw new IllegalArgumentException("Bitmap sizes are different!");}int width = bitmap1.getWidth();int height = bitmap1.getHeight();long diff = 0;for (int y = 0; y < height; y++) {for (int x = 0; x < width; x++) {int pixel1 = bitmap1.getPixel(x, y);int pixel2 = bitmap2.getPixel(x, y);int r1 = Color.red(pixel1);int g1 = Color.green(pixel1);int b1 = Color.blue(pixel1);int r2 = Color.red(pixel2);int g2 = Color.green(pixel2);int b2 = Color.blue(pixel2);// 计算 RGB 差异diff += Math.abs(r1 - r2);diff += Math.abs(g1 - g2);diff += Math.abs(b1 - b2);}}// 最大可能差异double maxDiff = 3L * 255 * width * height;// 返回 0 到 1 的值,越小表示相似度越高return (double) diff / maxDiff;
}

这段代码计算两张图片的 RGB 差异,返回的结果范围在 0-1 之间,数值越接近 0 表示图片越相似。

2. 基于直方图的比较

通过比较两张图片的颜色直方图来评估相似度。直方图可以捕捉图像的颜色分布,而不关心具体像素位置。

public static double compareHistograms(Bitmap bitmap1, Bitmap bitmap2) {int[] histogram1 = new int[256];int[] histogram2 = new int[256];// 计算两张图的灰度直方图for (int y = 0; y < bitmap1.getHeight(); y++) {for (int x = 0; x < bitmap1.getWidth(); x++) {int pixel1 = bitmap1.getPixel(x, y);int gray1 = (Color.red(pixel1) + Color.green(pixel1) + Color.blue(pixel1)) / 3;histogram1[gray1]++;int pixel2 = bitmap2.getPixel(x, y);int gray2 = (Color.red(pixel2) + Color.green(pixel2) + Color.blue(pixel2)) / 3;histogram2[gray2]++;}}// 计算直方图的差异double diff = 0;for (int i = 0; i < 256; i++) {diff += Math.abs(histogram1[i] - histogram2[i]);}return diff / (bitmap1.getWidth() * bitmap1.getHeight());
}

3. 使用 SSIM(结构相似性)

SSIM 是一种用来衡量两张图片结构相似性的算法,它比简单的像素差异或直方图比较更准确。Android SDK 没有内置的 SSIM 方法,但可以引入第三方库或者自己实现。SSIM 主要关注三方面:亮度、对比度和结构。

4. 感知哈希(pHash)

pHash 是一种图像哈希技术,它可以生成图片的“指纹”,然后比较两个哈希值的相似性。与传统哈希方法不同,pHash 对于图像的细微改变(例如缩放、旋转)不敏感。

可以通过第三方库实现 pHash,比如 ImageHash 库,或者自己实现基于 DCT(离散余弦变换)的算法。

// 引入第三方库 ImageHash 进行哈希比较
String hash1 = ImageHash.hash(bitmap1);
String hash2 = ImageHash.hash(bitmap2);int similarity = ImageHash.compare(hash1, hash2);

一般来说:

  • 对于简单的图像比较,基于像素差异的方式即可。
  • 如果要忽略图片的细微变动,直方图或感知哈希是更合适的选择。
  • SSIM 适用于对图像结构有更高要求的场景。

实现

图像比较的算法应用相当广泛, 本文基于感知哈希算法, 用于识别视频帧图像的左右两部分的相似度, 从而判断视频是否是一个左右眼的VR视频格式, 本文采用 感知哈希(pHash) 算法, 它非常适合处理具有细微变化的图像,如裁剪、缩放、亮度变化等。

感知哈希(pHash)是一种用于衡量图像相似度的算法,它通过将图像转换为频域信息,提取其视觉特征来生成一个哈希值。pHash 具有鲁棒性,能够忽略图像的小幅度变动、旋转和缩放等影响。下面是 pHash 算法的实现步骤及其原理。

pHash 算法的实现步骤

  1. 转换为灰度图:将图片转换为灰度图像,以便降低复杂度,并去除颜色信息的影响。

  2. 缩小尺寸:将图像缩小到一个固定的尺寸(例如 32x32),目的是去除高频细节,保留图片的整体特征。这一步骤在后续的离散余弦变换(DCT)中很重要。

  3. 离散余弦变换(DCT):对缩小后的图像执行离散余弦变换,将图像从空间域转换到频率域。这种转换能提取图像的低频信息,忽略高频噪声。

  4. 截取低频部分:只保留 DCT 结果的左上角部分(例如 8x8 的矩阵),因为这部分包含图像的主要信息。

  5. 计算均值:计算截取的低频部分的均值。

  6. 生成哈希值:将 DCT 中每个像素值与均值进行比较,生成一个二进制序列。如果某个像素值大于均值,置 1,否则置 0。最终的哈希值是由这个二进制序列构成。

参考pHash 算法实现

import android.graphics.Bitmap;
import android.graphics.Color;
import java.util.Arrays;public class ImagePHash {// 默认使用 32x32 大小private static final int SIZE = 32;// DCT 截取的大小(例如 8x8)private static final int SMALLER_SIZE = 8;public String getHash(Bitmap img) {// 1. 转换为灰度图像Bitmap grayImg = toGrayscale(img);// 2. 缩小图片Bitmap smallImg = Bitmap.createScaledBitmap(grayImg, SIZE, SIZE, false);// 3. 转换为二维数组double[][] vals = new double[SIZE][SIZE];for (int x = 0; x < SIZE; x++) {for (int y = 0; y < SIZE; y++) {vals[x][y] = Color.red(smallImg.getPixel(x, y));}}// 4. 对图像执行离散余弦变换(DCT)double[][] dctVals = applyDCT(vals);// 5. 截取 DCT 左上角的 8x8 部分double[] dctLowFreq = new double[SMALLER_SIZE * SMALLER_SIZE];for (int x = 0; x < SMALLER_SIZE; x++) {for (int y = 0; y < SMALLER_SIZE; y++) {dctLowFreq[x * SMALLER_SIZE + y] = dctVals[x][y];}}// 6. 计算均值double avg = Arrays.stream(dctLowFreq).average().orElse(0.0);// 7. 生成哈希值StringBuilder hash = new StringBuilder();for (double value : dctLowFreq) {hash.append(value > avg ? "1" : "0");}return hash.toString();}// 转换为灰度图像private Bitmap toGrayscale(Bitmap img) {int width = img.getWidth();int height = img.getHeight();Bitmap grayscaleImg = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);for (int y = 0; y < height; y++) {for (int x = 0; x < width; x++) {int pixel = img.getPixel(x, y);int red = Color.red(pixel);int green = Color.green(pixel);int blue = Color.blue(pixel);int gray = (red + green + blue) / 3;int newPixel = Color.rgb(gray, gray, gray);grayscaleImg.setPixel(x, y, newPixel);}}return grayscaleImg;}// 执行离散余弦变换(DCT)private double[][] applyDCT(double[][] f) {int N = f.length;double[][] F = new double[N][N];for (int u = 0; u < N; u++) {for (int v = 0; v < N; v++) {double sum = 0.0;for (int i = 0; i < N; i++) {for (int j = 0; j < N; j++) {sum += f[i][j] *Math.cos((2 * i + 1) * u * Math.PI / (2.0 * N)) *Math.cos((2 * j + 1) * v * Math.PI / (2.0 * N));}}double alphaU = (u == 0) ? Math.sqrt(1.0 / N) : Math.sqrt(2.0 / N);double alphaV = (v == 0) ? Math.sqrt(1.0 / N) : Math.sqrt(2.0 / N);F[u][v] = alphaU * alphaV * sum;}}return F;}// 比较两个哈希值,返回汉明距离(不同位数的个数)public int hammingDistance(String hash1, String hash2) {int distance = 0;for (int i = 0; i < hash1.length(); i++) {if (hash1.charAt(i) != hash2.charAt(i)) {distance++;}}return distance;}
}

对比效果如下(使用ListView 显示多张图片对比结果, 一帧视频图像从中间切割左右两部分, 分别显示在列表项的左右两侧, 中间的文字输出比较结果的汉明值, 值越小图像差异越小):
在这里插入图片描述
在这里插入图片描述

原始测试图片(从一个VR视频中截取出的视频帧):
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

代码分享:

test_img_diff.xml 布局

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:id="@+id/rlRoot"><ListView android:id="@+id/lv"android:layout_width="match_parent"android:layout_height="match_parent"/>
</RelativeLayout>

ListView 的item 布局: item_img_diff.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><ImageView android:id="@+id/ivLeft"android:layout_width="128dp"android:layout_height="72dp"/><ImageView android:id="@+id/ivRight"android:layout_width="128dp"android:layout_height="72dp"android:layout_alignParentRight="true"/><TextView android:id="@+id/tvRes"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:textSize="18sp"android:textColor="#FFFFFFFF"/>
</RelativeLayout>

主界面Activity: ImgDiffTester.java

public class ImgDiffTester extends Activity implements View.OnClickListener {final String TAG = "ImgDiffTester";ListView lv;ImgListAdapter adapter;@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.test_img_diff);findViewById(R.id.rlRoot).setOnClickListener(this);lv = (ListView) findViewById(R.id.lv);adapter = new ImgListAdapter();lv.setAdapter(adapter);startCompare();}void startCompare(){new Thread(){@Overridepublic void run() {File[] fs = new File("/sdcard/Download/").listFiles(new FileFilter() {@Overridepublic boolean accept(File file) {return file.getName().endsWith(".png");}});for(File f : fs){Bitmap bm = BitmapFactory.decodeFile(f.getAbsolutePath());compareBitmapAndShow(bm);}lv.post(new Runnable() {@Overridepublic void run() {adapter.notifyDataSetChanged();}});}}.start();}void compareBitmapAndShow(Bitmap bm){if(bm != null && bm.getWidth() > 0 && bm.getHeight() > 0) {final Bitmap bm1 = BitmapUtils.clipBitmapWidthBounds(bm, new Rect(0, 0, bm.getWidth() / 2, bm.getHeight()));//bm1 = BitmapFactory.decodeFile("/sdcard/l.png");final Bitmap bm2 = BitmapUtils.clipBitmapWidthBounds(bm, new Rect(bm.getWidth() / 2, 0, bm.getWidth(), bm.getHeight()));//bm2 = BitmapFactory.decodeFile("/sdcard/r.png");try {Bitmap[] scaled = new Bitmap[2];//scaled[0] = Bitmap.createBitmap(pHash.DCT_LENGTH, pHash.DCT_LENGTH, Bitmap.Config.ARGB_8888);//scaled[1] = Bitmap.createBitmap(pHash.DCT_LENGTH, pHash.DCT_LENGTH, Bitmap.Config.ARGB_8888);//int cmp = pHash.compareBitmap(bm1, bm2, scaled, false);long st = SystemClock.uptimeMillis();final int cmp = ImagePHash.compareBitmap(bm1, bm2);long et = SystemClock.uptimeMillis();Log.d(TAG, "compare " + cmp + " spend " + (et - st) + " ms");Item item = new Item();item.l = bm1;item.r = bm2;item.res = "Result: " + cmp + ", spend " + (et - st) + " ms";adapter.items.add(item);} catch (Exception e) {throw new RuntimeException(e);}}}public static class ImagePHash {// 默认使用 32x32 大小private static final int SIZE = 32;// DCT 截取的大小(例如 8x8)private static final int SMALLER_SIZE = 8;public static int compareBitmap(Bitmap bm1, Bitmap bm2){String h1 = getHash(bm1);String h2 = getHash(bm2);return hammingDistance(h1, h2);}@SuppressLint("NewApi")public static String getHash(Bitmap img) {long st = SystemClock.uptimeMillis();// 1. 转换为灰度图像Bitmap grayImg = toGrayscale(img);// 2. 缩小图片Bitmap smallImg = Bitmap.createScaledBitmap(grayImg, SIZE, SIZE, false);// 3. 转换为二维数组double[][] vals = new double[SIZE][SIZE];for (int x = 0; x < SIZE; x++) {for (int y = 0; y < SIZE; y++) {vals[x][y] = Color.red(smallImg.getPixel(x, y));}}long ct1 = SystemClock.uptimeMillis();// 4. 对图像执行离散余弦变换(DCT)double[][] dctVals = applyDCT(vals);long ct2 = SystemClock.uptimeMillis();// 5. 截取 DCT 左上角的 8x8 部分double[] dctLowFreq = new double[SMALLER_SIZE * SMALLER_SIZE];for (int x = 0; x < SMALLER_SIZE; x++) {for (int y = 0; y < SMALLER_SIZE; y++) {dctLowFreq[x * SMALLER_SIZE + y] = dctVals[x][y];}}// 6. 计算均值double avg = Arrays.stream(dctLowFreq).average().orElse(0.0);long ct3 = SystemClock.uptimeMillis();// 7. 生成哈希值StringBuilder hash = new StringBuilder();for (double value : dctLowFreq) {hash.append(value > avg ? "1" : "0");}Log.d("ImgDiff", (ct1 - st) + ", " + (ct2 - ct1));return hash.toString();}// 转换为灰度图像private static Bitmap toGrayscale(Bitmap img) {int width = img.getWidth();int height = img.getHeight();Bitmap grayscaleImg = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);for (int y = 0; y < height; y++) {for (int x = 0; x < width; x++) {int pixel = img.getPixel(x, y);int red = Color.red(pixel);int green = Color.green(pixel);int blue = Color.blue(pixel);int gray = (red + green + blue) / 3;int newPixel = Color.rgb(gray, gray, gray);grayscaleImg.setPixel(x, y, newPixel);}}return grayscaleImg;}// 执行离散余弦变换(DCT)private static double[][] applyDCT(double[][] f) {int N = f.length;double[][] F = new double[N][N];for (int u = 0; u < N; u++) {for (int v = 0; v < N; v++) {double sum = 0.0;for (int i = 0; i < N; i++) {for (int j = 0; j < N; j++) {sum += f[i][j] *Math.cos((2 * i + 1) * u * Math.PI / (2.0 * N)) *Math.cos((2 * j + 1) * v * Math.PI / (2.0 * N));}}double alphaU = (u == 0) ? Math.sqrt(1.0 / N) : Math.sqrt(2.0 / N);double alphaV = (v == 0) ? Math.sqrt(1.0 / N) : Math.sqrt(2.0 / N);F[u][v] = alphaU * alphaV * sum;}}return F;}// 比较两个哈希值,返回汉明距离(不同位数的个数)public static int hammingDistance(String hash1, String hash2) {int distance = 0;for (int i = 0; i < hash1.length(); i++) {if (hash1.charAt(i) != hash2.charAt(i)) {distance++;}}return distance;}}class ImgListAdapter extends BaseAdapter{ArrayList<Item> items = new ArrayList<>();@Overridepublic int getCount() {return items.size();}@Overridepublic Object getItem(int i) {return items.get(i);}@Overridepublic long getItemId(int i) {return i;}@Overridepublic View getView(int pos, View view, ViewGroup viewGroup) {if(view == null){view = getLayoutInflater().inflate(R.layout.item_img_diff, null, false);}((ImageView)view.findViewById(R.id.ivLeft)).setImageBitmap(items.get(pos).l);((ImageView)view.findViewById(R.id.ivRight)).setImageBitmap(items.get(pos).r);((TextView)view.findViewById(R.id.tvRes)).setText(items.get(pos).res);return view;}}class Item{Bitmap l, r;String res;}
}

温馨提示
本文算法及用例仅供参考, 未经大量测试验证
请谨慎阅读参考

参考

Android Bitmap亮度调节、灰度化、二值化、相似距离实现

相关文章:

Android 图片相识度比较(pHash)

概述 在 Android 中&#xff0c;要比对两张 Bitmap 图片的相似度&#xff0c;常见的方法有基于像素差异、直方图比较、或者使用一些更高级的算法如 SSIM&#xff08;结构相似性&#xff09;和感知哈希&#xff08;pHash&#xff09;。 1. 基于像素的差异比较 可以逐像素比较…...

Gitlab 完全卸载–亲测可行

1、停止gitlab gitlab-ctl stop2.卸载gitlab&#xff08;注意这里写的是gitlab-ce&#xff09; rpm -e gitlab-ce 3、查看gitlab进程 ps aux | grep gitlab 4、杀掉第一个进程&#xff08;就是带有好多.............的进程&#xff09; 5、删除所有包含gitlab文件 find / …...

gitlab操作和管理

详细的说明下这几条指令&#xff1a; Git global setup git config --global user.name “” git config --global user.email “” Create a new repository git clone ssh://git12/letect.git cd vlm-event-secondary-detect git switch -c main touch README.md git add RE…...

ctfshow-web入门-反序列化(web254-web258)

目录 1、web254 2、web255 3、web256 4、web257 5、web258 1、web254 传入符合要求的用户名和密码即可&#xff1a; ?usernamexxxxxx&passwordxxxxxx 拿到 flag&#xff1a;ctfshow{e4795ccd-6bff-44b6-a15c-6c679d802e61} 2、web255 整体逻辑代码和上一道差不多 新…...

repo 命令大全详解(第十一篇 repo init)

repo forall 命令用于在指定的项目上执行给定的命令&#xff0c;非常适合批量操作。 参数分类及解释 基本参数 [<project>...]: 可选&#xff0c;指定要操作的项目。如果不指定&#xff0c;则对所有项目执行命令。 示例: repo forall my_project -c "git status&q…...

ComfyUI | 全新ComfyUI前端操作指南:提升你的工作速度!

随着WebUI基本停更&#xff0c;越来越多的AI创作者转向了ComfyUI。 ComfyUI最大的优势是简洁、高效、占用显存低&#xff0c;工作流模式虽然有一点入门难度&#xff0c;但一旦上手&#xff0c;操作非常舒适。 由于原Stable Diffusion团队的参与&#xff0c;ComfyUI的易用度也…...

nginx解决非人类使用http打开的443,解决网安漏扫时误扫443端口带来的问题

一、问题描述 正常访问https的站点时&#xff0c;使用网址https://www.baidu.com&#xff0c;但会有一种错误的访问请求http://www.baidu.com:443&#xff0c;一般都是非人类所为&#xff0c;如漏洞扫描工具&#xff0c;那么请求以后带来的后果是个错误页面 400 Bad Request T…...

黑马 | Reids | 基础篇

黑马reids基础篇 文章目录 黑马reids基础篇一.初始Redis1.1SQL 和 NoSql的区别1.1.1结构化和非结构化1.1.2关联和非关联1.1.3查询方式1.1.4 事务1.1.5总结 1.2 认识Redis1.3 Redis安装启动默认启动&#xff1a;后台启动&#xff1a;开机自启 1.4 Redis客户端1.4.1.Redis命令行客…...

SAP-换登录界面图片

SMW0 二、SM30 &#xff08;将value值删除&#xff0c;登录图片恢复默认&#xff09; 重新登录&#xff0c;更改成功。...

移动 Web核心笔记(二)

空间转换 空间&#xff1a;是从坐标轴角度定义的 X 、Y 和 Z 三条坐标轴构成了一个立体空间&#xff0c;Z 轴位置与视线方向相同。 空间转换也叫 3D转换 属性&#xff1a;transform 平移 /*单独设置 z轴效果不明显*/ transform: translate3d(x, y, z); transform: translateX(…...

MySQL创建和管理表

1. 基础知识 存储数据是处理数据的第一步&#xff0c;只有正确地把数据存储起来&#xff0c;才能进行有效的处理和分析。 在 MySQL 中&#xff0c;一个完整的数据存储过程总共有 4 步&#xff0c;分别是创建数据库、确认字段、创建数据表、插入数据。 从系统架构的层次上看…...

【从零开始的LeetCode-算法】910. 最小差值 II

给你一个整数数组 nums&#xff0c;和一个整数 k 。 对于每个下标 i&#xff08;0 < i < nums.length&#xff09;&#xff0c;将 nums[i] 变成 nums[i] k 或 nums[i] - k 。 nums 的 分数 是 nums 中最大元素和最小元素的差值。 在更改每个下标对应的值之后&#xf…...

周报 | 24.10.14-24.10.20文章汇总

为了更好地整理文章和发表接下来的文章&#xff0c;以后每周都汇总一份周报。 周报 | 24.10.7-24.10.13文章汇总-CSDN博客 OpenCV与AI深度学习 | T-Rex Label &#xff01;超震撼 AI 自动标注工具&#xff0c;开箱即用、检测一切-CSDN博客 计算机视觉与机器学习 | 目标检测 …...

Codeforce 980 Div2 A-D 题解

A. Profitable Interest Rate 原题 A. Profitable Interest Rate 思路 易推出公式 2 * a - b 代码 #include <bits/stdc.h> //#define int long long#define F(i, a, b) for (int i (a); i < (b); i) #define dF(i, a, b) for (int i (a); i > (b); i--)usi…...

一次代码优化的过程

场景说明&#xff1a; wpf项目&#xff0c;有4个不同的页面&#xff0c;共用一个next按钮&#xff0c;实现点击后跳转到下一个页面。 第一个页面是导入文件&#xff0c;当有2个及以上文件时&#xff0c;会弹窗提示。如下图所示&#xff1a; 之前和之后的代码对比&#xff1a; 之…...

多线程的学习(1)

线程的创建方式 1.继承Thread类 package duoXianCheng;public class MyThread extends Thread{public void run(){System.out.println("hoh");}public static void main(String[] args) {MyThread m1 new MyThread();m1.start();//start启动线程&#xff0c;调用重…...

PyCharm借助MobaXterm跳板机连接服务器

服务器信息&#xff1a; Step 1 MovaXterm→Session→SSH输入服务器信息 Step 2 MovaXterm→Session→SSH→Network setting→SSG gateway(jump host) 输入跳板机信息 键入密码即可 Step 3 MovaXterm→Tunneling→New SSH tunnel 依次输入&#xff1a;A本机端口&#xff0c…...

计算机毕业论文基于Android 的签到系统设计与实现

计算机专业本科毕业设计(论文)开题报告 毕业设计(论文)题目:基于Android的签到系统设计与实现 文章目录 毕业设计论文开题报告一、课题的目的及意义(含国内外的研究现状分析):二、课题任务、重点研究内容、实现途径、条件:摘 要1. 绪论1.1. 研究背景1.2. 研究现状1.3.…...

量化学习-02

1、宏观经济学基础概念 宏观经济简单背景 宏观经济&#xff0c;就是在宏观范畴以全局视角观察经济现象&#xff0c;分析其中的经济总量。该宏观范畴所包含的范围可以指一个国家或地区&#xff0c;是由众多微观个体组成的一个经济体&#xff0c;而这里面的微观个体可以指一个家…...

SAP_MM模块-设置业务合作伙伴类型字段必输(多种方案)

一、业务背景 公司需要把供应商增加一个细分的维度&#xff0c;并且要求该字段设置为必输&#xff0c;防止用户新增供应商时忘记维护。这里给用户找了一个分类的字段&#xff1a;业务合作伙伴类型&#xff0c;本文主要讲解如何设置该字段设置为必填&#xff1b; 注意&#xff…...

OpenLayers 可视化之热力图

注&#xff1a;当前使用的是 ol 5.3.0 版本&#xff0c;天地图使用的key请到天地图官网申请&#xff0c;并替换为自己的key 热力图&#xff08;Heatmap&#xff09;又叫热点图&#xff0c;是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...

UDP(Echoserver)

网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法&#xff1a;netstat [选项] 功能&#xff1a;查看网络状态 常用选项&#xff1a; n 拒绝显示别名&#…...

高频面试之3Zookeeper

高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个&#xff1f;3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制&#xff08;过半机制&#xff0…...

在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module

1、为什么要修改 CONNECT 报文&#xff1f; 多租户隔离&#xff1a;自动为接入设备追加租户前缀&#xff0c;后端按 ClientID 拆分队列。零代码鉴权&#xff1a;将入站用户名替换为 OAuth Access-Token&#xff0c;后端 Broker 统一校验。灰度发布&#xff1a;根据 IP/地理位写…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)

宇树机器人多姿态起立控制强化学习框架论文解析 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架&#xff08;一&#xff09; 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...

CVPR2025重磅突破:AnomalyAny框架实现单样本生成逼真异常数据,破解视觉检测瓶颈!

本文介绍了一种名为AnomalyAny的创新框架&#xff0c;该方法利用Stable Diffusion的强大生成能力&#xff0c;仅需单个正常样本和文本描述&#xff0c;即可生成逼真且多样化的异常样本&#xff0c;有效解决了视觉异常检测中异常样本稀缺的难题&#xff0c;为工业质检、医疗影像…...

SQL Server 触发器调用存储过程实现发送 HTTP 请求

文章目录 需求分析解决第 1 步:前置条件,启用 OLE 自动化方式 1:使用 SQL 实现启用 OLE 自动化方式 2:Sql Server 2005启动OLE自动化方式 3:Sql Server 2008启动OLE自动化第 2 步:创建存储过程第 3 步:创建触发器扩展 - 如何调试?第 1 步:登录 SQL Server 2008第 2 步…...

ubuntu22.04有线网络无法连接,图标也没了

今天突然无法有线网络无法连接任何设备&#xff0c;并且图标都没了 错误案例 往上一顿搜索&#xff0c;试了很多博客都不行&#xff0c;比如 Ubuntu22.04右上角网络图标消失 最后解决的办法 下载网卡驱动&#xff0c;重新安装 操作步骤 查看自己网卡的型号 lspci | gre…...

消防一体化安全管控平台:构建消防“一张图”和APP统一管理

在城市的某个角落&#xff0c;一场突如其来的火灾打破了平静。熊熊烈火迅速蔓延&#xff0c;滚滚浓烟弥漫开来&#xff0c;周围群众的生命财产安全受到严重威胁。就在这千钧一发之际&#xff0c;消防救援队伍迅速行动&#xff0c;而豪越科技消防一体化安全管控平台构建的消防“…...

Spring Boot + MyBatis 集成支付宝支付流程

Spring Boot MyBatis 集成支付宝支付流程 核心流程 商户系统生成订单调用支付宝创建预支付订单用户跳转支付宝完成支付支付宝异步通知支付结果商户处理支付结果更新订单状态支付宝同步跳转回商户页面 代码实现示例&#xff08;电脑网站支付&#xff09; 1. 添加依赖 <!…...