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

AI图像相似性搜索对比:VIT, CLIP, DINO-v2, BLIP-2

图像相似性搜索的核心在于一个简单的想法:图像可以表示为高维空间中的向量。当两个图像相似时,它们的向量应该在这个空间中占据相似的位置。我们可以通过测量角度(或余弦相似度)来确定这些向量的相似程度。如果角度小,图像就接近(相似)。如果角度大(不同),图像就会相距很远。这就像在公寓大楼里寻找邻居一样,但方式要抽象得多。使用不同的 AI 模型,例如 ViTCLIPBLIPEfficientNetDINO-v2VGG16比较图像并查看它们的相似之处。
在这里插入图片描述

模型介绍

关于图像相似度计算的几种深度学习方法,以下是对几个模型的介绍,包括它们的优缺点:

1. ViT(Vision Transformer)

ViT是Google在2020年提出的模型,将Transformer架构应用于图像分类任务。ViT通过将图像分割成多个小块(patches),然后将这些小块线性映射到低维空间,并添加位置编码后输入到Transformer Encoder中进行处理。
优点

  • 全局感受野:ViT能够捕获图像的全局特征,这在CNN中较难实现。
  • 可扩展性:模型的效果随着模型大小的增加而提升,表现出很好的可扩展性。
  • 较少的训练资源:在大规模数据集上预训练后,ViT在多个中小型图像识别基准上的表现优于SOTA的CNN,同时需要的训练资源更少。

缺点

  • 缺乏归纳偏置:ViT不具有CNN的归纳偏置,如平移不变性和局部感受野,这可能需要额外的技术来补偿。
  • 对数据量要求高:ViT在小数据集上的表现可能不如CNN,需要大量数据进行预训练才能发挥其优势。

2. CLIP(Contrastive Language-Image Pre-Training)

CLIP是OpenAI在2021年发布的多模态预训练神经网络,通过对比学习的方式,将图像和文本映射到共享的向量空间中,实现图像和文本之间的语义关联。

优点

  • 零样本学习:CLIP在零样本学习任务中表现出色,不需要看到新的图像或文本的训练示例就能进行预测。
  • 简洁有效的架构:模型架构简洁,效果好,适用于多种视觉和语言任务。

缺点

  • 对标注数据的依赖:尽管CLIP在预训练阶段不需要大量标注数据,但在某些任务中,如图像分类,可能需要额外的标注数据来微调模型。

3. BLIP(Bootstrapped Language-Image Pretraining)

BLIP是Salesforce提出的多模态Transformer模型,旨在统一视觉理解任务和生成任务。BLIP通过引入Captioner和Filter模块来提高数据质量和数量,从而提升模型性能。
优点

  • 理解和生成能力:BLIP兼具图文多模态的理解和生成能力,适用于多种视觉语言任务。
  • 数据质量提升:通过Captioner和Filter模块,BLIP能够去除网络资源中的文本噪声,提高模型性能。

缺点

  • 训练成本:BLIP的训练需要较大的网络架构和数据集,导致较大的训练代价。

4. EfficientNet

EfficientNet是Google提出的模型,通过复合缩放方法(同时考虑网络深度、宽度和图像分辨率)来提高模型的效率和准确性。

优点

  • 高效率:EfficientNet在保持高准确率的同时,模型更小、更快,提高了网络的实用性和工业落地可能。
  • 系统性模型缩放:EfficientNet提出了一种系统性的方法来缩放模型,而不是随意增加网络的深度或宽度。

缺点

  • 对资源的需求:尽管EfficientNet在效率上有显著提升,但在某些情况下,可能仍然需要较多的计算资源。

5. DINO-v2

DINO-v2是Meta AI发布的自监督学习模型,能够抽取强大的图像特征,且在下游任务上不需要微调。

优点

  • 无需微调:DINO-v2可以直接用作多种计算机视觉任务的骨干网络,无需微调。
  • 自监督学习:DINO-v2使用自监督学习,可以从任何图像集合中学习,不依赖于大量的标记数据。

缺点

  • 对数据集的依赖:虽然DINO-v2可以从任何图像集合中学习,但其性能可能依赖于数据集的质量和多样性。

步骤1:数据准备

从维基百科抓取了国旗图像,将世界各地国家的国旗变成了一个数据集。

图像相似性搜索的核心在于一个简单的想法:图像可以表示为高维空间中的向量。当两个图像相似时,它们的向量应该在这个空间中占据相似的位置。我们可以通过测量角度(或余弦相似度)来确定这些向量的相似程度。如果角度小,图像就接近(相似)。如果角度大(不同),图像就会相距很远。这就像在公寓大楼里寻找邻居一样,但方式要抽象得多。


import pandas as pd
flags_df = pd.read_csv('national_flags.csv')  
print(flags_df)

在这里插入图片描述

步骤2:特征提取

提取特征,将每个模型获取标志的图像并将其转换为特征向量,并将其特征转换为数字列表。在本实验中,将使用 Huggingface 的特征转换器库来进行特征提取。

  • EfficientNet: 通过平均最后一个隐藏层输出的空间维度来提取标志特征,重点关注细粒度模式。
image_processor = AutoImageProcessor.from_pretrained("google/efficientnet-b7")
model = EfficientNetModel.from_pretrained("google/efficientnet-b7")# prepare input image
inputs = image_processor(img, return_tensors='pt')with torch.no_grad():outputs = model(**inputs, output_hidden_states=True)embedding = outputs.hidden_states[-1]
embedding = torch.mean(embedding, dim=[2,3])
  • ViT: 使用其转换器架构中第一个标记的最后隐藏状态,捕获局部和全局视觉特征。
image_processor = AutoImageProcessor.from_pretrained("google/vit-large-patch16-224-in21k")
model = ViTModel.from_pretrained("google/vit-large-patch16-224-in21k")# prepare input image
inputs = image_processor(img, return_tensors='pt')with torch.no_grad():outputs = model(**inputs)
embedding = outputs.last_hidden_state
embedding = embedding[:, 0, :].squeeze(1)
  • DINO-v2: 通过专注于自我监督学习来生成嵌入,利用第一个标记来捕获以对象为中心的细节。

image_processor = AutoImageProcessor.from_pretrained('facebook/dinov2-base')
model = AutoModel.from_pretrained('facebook/dinov2-base')# prepare input image
inputs = image_processor(img, return_tensors='pt')with torch.no_grad():outputs = model(**inputs)
embedding = outputs.last_hidden_state
embedding = embedding[:, 0, :].squeeze(1)
  • CLIP: 结合图像和文本嵌入,使用图像特征来理解视觉概念以及来自配对文本的上下文数据。
image_processor = CLIPProcessor.from_pretrained("openai/clip-vit-base-patch32")
model = CLIPModel.from_pretrained("openai/clip-vit-base-patch32")# prepare input image
inputs = image_processor(images=img, return_tensors='pt', padding=True)with torch.no_grad():embedding = model.get_image_features(**inputs) 
  • BLIP-2: 采用视觉语言模型,通过其以查询为中心的转换器 (Q-Former) 提取特征来捕获图像语义和关系。
image_processor = Blip2Processor.from_pretrained("Salesforce/blip2-opt-2.7b")
model = Blip2Model.from_pretrained("Salesforce/blip2-opt-2.7b", torch_dtype=torch.float16)inputs = image_processor(images=img, return_tensors='pt', padding=True)
print('input shape: ', inputs['pixel_values'].shape)with torch.no_grad():outputs = model.get_qformer_features(**inputs)
embedding = outputs.last_hidden_state
embedding = embedding[:, 0, :].squeeze(1)
  • VGG16: 一种 CNN 模型,通过应用一堆卷积层来输出标记嵌入,强调分层图像表示。
model = models.vgg16(pretrained=True) 
model.eval()  # Set the model to evaluation modebatch_t = torch.unsqueeze(img, 0)with torch.no_grad():embedding = model(batch_t)

接着将每个模型提取的图像特征,转换为DataFrame数据,这将作为相似性分析的基础。

步骤 3:使用FAISS余弦相似度

通过上面的方法将图像通过各个模型进行特征提取,并将特征转换成dataframe的形式。利用余弦相似度来计算图像相似程度。余弦相似度比较两个向量的方向,使其能够有效地根据模式而不是大小来识别关系。这种方法在分析数据相似度上特别有用,其中重点是相对形状和像素元素,而不是特征向量的绝对大小。

  • 归一化:每个特征向量都归一化为单位长度,因此余弦相似度可以计算为向量的点积。这确保相似性反映了向量之间的角度。

  • 用于相似性搜索的 FAISS:利用 FAISS(一个针对高效相似性搜索而优化的库),根据其标准化特征向量,根据测试的数据查找前 K 个最相似的国家/地区。在大型旗帜图像数据集上进行快速且可扩展的比较。

def clean_feature_string(feature_str):cleaned_str = re.sub(r'[\[\]]', '', feature_str)  # Remove bracketscleaned_values = np.fromstring(cleaned_str, sep=' ')  # Parse values into numpy arrayreturn cleaned_values# Function to get top K similar countries using FAISS
def get_top_k_similar_countries(input_country, df, k=5):countries = df['Country'].valuesfeatures = np.array([clean_feature_string(f) for f in df['features'].values])# Find the index of the input countrytry:input_idx = list(countries).index(input_country)except ValueError:return f"Country '{input_country}' not found in the dataset."input_embedding = features[input_idx].reshape(1, -1)# Normalize the feature vectors for cosine similarityfeatures_normalized = features / np.linalg.norm(features, axis=1, keepdims=True)# Create a FAISS index for similarity searchdim = features.shape[1]index = faiss.IndexFlatIP(dim)  # Add all features to the FAISS indexindex.add(features_normalized)# Search for the top K most similar countriesdistances, top_k_idx = index.search(input_embedding, k+1)  # k+1 to exclude the country itself# Return top K countries with their similarity scoresreturn [(countries[i], distances[0][j]) for j, i in enumerate(top_k_idx[0]) if i != input_idx]## Display top 5 similar flags 
top_5_countries = get_top_k_similar_countries(country, k=5)for idx, (country, score) in enumerate(top_5_countries):# Load the flag image for each country from the local folderimg = load_local_image(country)display(img)

步骤4: 模型测试

测试 1:乍得和罗马尼亚 所有模型都返回“罗马尼亚”作为最佳匹配。
在这里插入图片描述
测试 2:澳大利亚和新西兰 所有模型都正确识别了新西兰。
在这里插入图片描述

完整版代码如下:


# script to generate embeddings and perform similarity searchesimport pandas as pd
import torch
from transformers import AutoImageProcessor, EfficientNetModel, ViTModel, AutoModel, CLIPProcessor, CLIPModel, Blip2Processor, Blip2Model
from torchvision import models, transforms
import numpy as np
import os
import re
import faiss
flags_df = pd.read_csv('national_flags.csv')  # Uncomment if you're loading from a CSV
IMAGE_DIR = "images"
def load_local_image(country_name):# Sanitize the country name to match the local image file naming conventionsanitized_country_name = country_name.replace(" ", "_").replace("[", "").replace("]", "")# Path to the local image fileimage_path = os.path.join(IMAGE_DIR, f"{sanitized_country_name}.png")# Check if the image exists in the folderif os.path.exists(image_path):img = Image.open(image_path)# Convert image to RGB if not already in that modeif img.mode != 'RGB':img = img.convert('RGB')return imgelse:print(f"Image for {country_name} not found.")return None
#ViTdef extract_features_vit(country):image_processor = AutoImageProcessor.from_pretrained("google/vit-large-patch16-224-in21k")model = ViTModel.from_pretrained("google/vit-large-patch16-224-in21k")# prepare input imageimg = load_local_image(country)inputs = image_processor(img, return_tensors='pt')with torch.no_grad():outputs = model(**inputs)embedding = outputs.last_hidden_stateembedding = embedding[:, 0, :].squeeze(1)return embedding.numpy()
#EfficientNetdef extract_features_efficientNet(country):# load pre-trained image processor for efficientnet-b7 and model weightimage_processor = AutoImageProcessor.from_pretrained("google/efficientnet-b7")model = EfficientNetModel.from_pretrained("google/efficientnet-b7")# prepare input imageimg = load_local_image(country)inputs = image_processor(img, return_tensors='pt')with torch.no_grad():outputs = model(**inputs, output_hidden_states=True)embedding = outputs.hidden_states[-1]embedding = torch.mean(embedding, dim=[2,3])return embedding.numpy()#DINO-v2def extract_features_DINO_v2(country):# load pre-trained image processor for efficientnet-b7 and model weightimage_processor = AutoImageProcessor.from_pretrained('facebook/dinov2-base')model = AutoModel.from_pretrained('facebook/dinov2-base')# prepare input imageimg = load_local_image(country)inputs = image_processor(img, return_tensors='pt')with torch.no_grad():outputs = model(**inputs)embedding = outputs.last_hidden_stateembedding = embedding[:, 0, :].squeeze(1)return embedding.numpy()#CLIPdef extract_features_clip(country):# load pre-trained image processor for efficientnet-b7 and model weightimage_processor = CLIPProcessor.from_pretrained("openai/clip-vit-base-patch32")model = CLIPModel.from_pretrained("openai/clip-vit-base-patch32")# prepare input imageimg = load_local_image(country)inputs = image_processor(images=img, return_tensors='pt', padding=True)with torch.no_grad():embedding = model.get_image_features(**inputs) return embedding.numpy()#Blip 2def extract_features_blip(country):image_processor = Blip2Processor.from_pretrained("Salesforce/blip2-opt-2.7b")model = Blip2Model.from_pretrained("Salesforce/blip2-opt-2.7b", torch_dtype=torch.float16)img = load_local_image(country)inputs = image_processor(images=img, return_tensors='pt', padding=True)print('input shape: ', inputs['pixel_values'].shape)with torch.no_grad():outputs = model.get_qformer_features(**inputs)embedding = outputs.last_hidden_stateembedding = embedding[:, 0, :].squeeze(1)return embedding.numpy()#vgg16def extract_features_vgg16(country):model = models.vgg16(pretrained=True) model.eval()  # Set the model to evaluation mode# Define the transformation to preprocess the imagepreprocess = transforms.Compose([transforms.Resize(256),transforms.CenterCrop(224),transforms.ToTensor(),transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),])img = load_local_image(country)img_t = preprocess(img)batch_t = torch.unsqueeze(img_t, 0)with torch.no_grad():embedding = model(batch_t)return embedding.numpy()# Extract features for all flags
flags_df['features'] = flags_df['Country'].apply(extract_features_vit)
#export embeddings to CSV
flags_df.to_csv('national_flag_embeddings_blip.csv', index=False)
#Cosine similarity with FAISSdf = pd.read_csv('embeddings/national_flag_embeddings_vit.csv')
country = "Australia"def clean_feature_string(feature_str):cleaned_str = re.sub(r'[\[\]]', '', feature_str)  # Remove bracketscleaned_values = np.fromstring(cleaned_str, sep=' ')  # Parse values into numpy arrayreturn cleaned_values# Function to get top K similar countries using FAISS
def get_top_k_similar_countries(input_country, df, k=5):countries = df['Country'].valuesfeatures = np.array([clean_feature_string(f) for f in df['features'].values])# Find the index of the input countrytry:input_idx = list(countries).index(input_country)except ValueError:return f"Country '{input_country}' not found in the dataset."input_embedding = features[input_idx].reshape(1, -1)# Normalize the feature vectors for cosine similarityfeatures_normalized = features / np.linalg.norm(features, axis=1, keepdims=True)# Create a FAISS index for similarity searchdim = features.shape[1]index = faiss.IndexFlatIP(dim)  # Add all features to the FAISS indexindex.add(features_normalized)# Search for the top K most similar countriesdistances, top_k_idx = index.search(input_embedding, k+1)  # k+1 to exclude the country itself# Return top K countries with their similarity scoresreturn [(countries[i], distances[0][j]) for j, i in enumerate(top_k_idx[0]) if i != input_idx]# Display top 5 similar flags 
top_5_countries = get_top_k_similar_countries(country, k=5)for idx, (country, score) in enumerate(top_5_countries):# Load the flag image for each country from the local folderimg = load_local_image(country)display(img)

获取数据代码:

 script to scrape flag images from Wikipedia and download images
import pandas as pd
import requests
from bs4 import BeautifulSoup
import os
import pandas as pd
import requests
from PIL import Image
from io import BytesIO
# URL of the Wikipedia page
url = "https://en.wikipedia.org/wiki/List_of_national_flags_of_sovereign_states"# Send a GET request to the URL
response = requests.get(url)# Parse the content of the page with BeautifulSoup
soup = BeautifulSoup(response.content, 'html.parser')# Find the table with the flags
table = soup.find('table', class_='wikitable')# Initialize lists to store the names and images
names = []
images = []# Iterate through the rows of the table
for row in table.find_all('tr')[1:]:  # Skip the header rowflag_cell = row.find('td')name_cell = row.find('th')  # Extract the name cell# Check if both cells are foundif flag_cell and name_cell:# Extract the country namename = name_cell.get_text(strip=True)# Extract the flag image URL (from the <img> tag)img_tag = flag_cell.find('img')if img_tag and img_tag.has_attr('src'):# Construct the full image URLimg_url = "https:" + img_tag['src']else:img_url = None# Append the results to the listsnames.append(name)images.append(img_url)# Create a DataFrame with the results
flags_df = pd.DataFrame({'Country': names,'Flag Image': images
})# Display the DataFrame# Optionally, save the DataFrame to a CSV file
flags_df.to_csv('national_flags.csv', index=False)

相关文章:

AI图像相似性搜索对比:VIT, CLIP, DINO-v2, BLIP-2

图像相似性搜索的核心在于一个简单的想法&#xff1a;图像可以表示为高维空间中的向量。当两个图像相似时&#xff0c;它们的向量应该在这个空间中占据相似的位置。我们可以通过测量角度&#xff08;或余弦相似度&#xff09;来确定这些向量的相似程度。如果角度小&#xff0c;…...

【tomcat系列漏洞利用】

Tomcat 服务器是一个开源的轻量级Web应用服务器&#xff0c;在中小型系统和并发量小的场合下被普遍使用。主要组件&#xff1a;服务器Server&#xff0c;服务Service&#xff0c;连接器Connector、容器Container。连接器Connector和容器Container是Tomcat的核心。一个Container…...

前端学习-盒子模型(十八)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 盒子模型组成 边框 语法 边框简写 代码示例 表格的细线边框 语法 内边距 内边距复合写法 外边距 外边距典型应用 外边距合并 清除内外边距 总结 前…...

【C++】类和对象(十二):实现日期类

大家好&#xff0c;我是苏貝&#xff0c;本篇博客带大家了解C的实现日期类&#xff0c;如果你觉得我写的还不错的话&#xff0c;可以给我一个赞&#x1f44d;吗&#xff0c;感谢❤️ 目录 1 /!/>/</>/<运算符重载2 /-//-运算符重载(A) 先写&#xff0c;再通过写(B…...

文章解读与仿真程序复现思路——电网技术EI\CSCD\北大核心《提升系统频率支撑能力的“车-氢”柔性可控负荷协同构网控制》

本专栏栏目提供文章与程序复现思路&#xff0c;具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源…...

异或的性质

交换两个变量的值&#xff0c;不使用第三个变量。 即a3,b5,交换之后a5,b3; 有两种解法, 一种用算术算法, 一种用^(异或) a a b; b a - b; a a - b; or a a^b;// 只能对int,char… b a^b; a a^b; or a ^ b ^ a; 异或交换两个变量值的方法是利用了异或运算的特性。下面是…...

新一代Webshell管理器

工具介绍 游魂是一个开源的Webshell管理器&#xff0c;提供更为方便的界面和更为简单易用的功能&#xff0c;可配合或代替其他webshell管理器&#xff0c;帮助用户在各类渗透场景中控制目标机器。游魂不仅支持常见的一句话webshell以及常见Webshell管理器的功能&#xff0c;还…...

「iOS」——知乎日报一二周总结

知乎日报仿写 前言效果Manager封装网络请求线程冲突问题下拉刷新添加网络请求的图片通过时间戳和日期格式化获取时间 总结 前言 前两周内容的仿写&#xff0c;主要完成了首页的仿写&#xff0c;进度稍慢。 效果 Manager封装网络请求 知乎日报的仿写需要频繁的申请网络请求&am…...

windows C#-匿名类型

匿名类型提供了一种方便的方法&#xff0c;可用来将一组只读属性封装到单个对象中&#xff0c;而无需首先显式定义一个类型。 类型名由编译器生成&#xff0c;并且不能在源代码级使用。 每个属性的类型由编译器推断。 可结合使用 new 运算符和对象初始值设定项创建匿名类型。 …...

CryptoHack 简介

CryptoHack 简介 文章目录 CryptoHack 简介一、python的安装&#xff0c;运行二、ASCII码三、十六进制四、Base64五、字节和大整数六、XOR1.基本2.xor属性3.xor隐藏字节4.cryptohack——You either know, XOR you dont 一、python的安装&#xff0c;运行 二、ASCII码 chr()函数…...

transformControls THREE.Object3D.add: object not an instance of THREE.Object3D.

把scene.add(transformControls);改为scene.add(transformControls.getHelper());...

游戏开发与游戏运营:哪个更难?

在探讨游戏产业时&#xff0c;游戏开发和游戏运营是两个至关重要的环节。它们各自承担着不同的职责&#xff0c;共同推动着游戏产品的成功与发展。然而&#xff0c;关于哪个环节更难的问题&#xff0c;并没有一个绝对的答案&#xff0c;因为两者都涉及复杂的流程、专业技能和独…...

大模型在自动化渗透测试中的应用

1. 引言 随着人工智能技术的快速发展&#xff0c;特别是大模型&#xff08;如GPT-3、GPT-4等&#xff09;的出现&#xff0c;自动化渗透测试领域迎来了新的机遇。大模型具有强大的自然语言处理能力和生成能力&#xff0c;能够在多个环节提升渗透测试的效率和准确性。本文将详细…...

《AI在企业战略中的关键地位:以微软和阿里为例》

内容概要 在当今商业环境中&#xff0c;人工智能&#xff08;AI&#xff09;的影响力如滔滔洪水&#xff0c;愈演愈烈。文章将揭示AI在企业战略中的崛起&#xff0c;尤其以微软和阿里巴巴为代表的企业&#xff0c;这两家科技巨头通过不同方式&#xff0c;将智能技术融入其核心…...

C语言 | Leetcode C语言题解之第537题复数乘法

题目&#xff1a; 题解&#xff1a; bool parseComplexNumber(const char * num, int * real, int * image) {char *token strtok(num, "");*real atoi(token);token strtok(NULL, "i");*image atoi(token);return true; };char * complexNumberMulti…...

Vue如何实现数据的双向绑定和局部更新?

1、Vue如何实现数据的双向绑定和局部更新&#xff1f; Vue.js中数据的双向绑定和局部更新可以通过v-model指令来实现。v-model是一个内置的双向数据绑定机制&#xff0c;用于将输入元素&#xff08;如input、textarea、select等&#xff09;与Vue实例的数据进行双向绑定。 在…...

java学习1

一、运算符 1.算术运算符 在代码中&#xff0c;如果有小数参与计算&#xff0c;结果有可能不精确 1-1.隐式转换和强制转换 数字进行运算时&#xff0c;数据类型不一样不能运算&#xff0c;需要转成一样的&#xff0c;才能运算 &#xff08;1&#xff09;隐式转换&#xff1a…...

如何缩小PPT演示文稿的大小?

有时候PPT的磁盘空间一不小心就变得意想不到的大&#xff0c;比如上百MB&#xff0c;该如何缩小PPT的大小从而便于上传或者携带呢&#xff1f; 导致PPT大的原因&#xff1a; 媒体文件在插入或者复制到演示文稿里会被直接涵盖在其中&#xff08;.pptx版本&#xff09;&#xf…...

闯关leetcode——234. Palindrome Linked List

大纲 题目地址内容 解题代码地址 题目 地址 https://leetcode.com/problems/palindrome-linked-list/description/ 内容 Given the head of a singly linked list, return true if it is a palindrome or false otherwise. Example 1: Input: head [1,2,2,1] Output: tru…...

通过源码分析类加载器里面可以加载的类

类列表 每一个ClassLoader里面的类列表&#xff0c;类的数量都是固定的。 对上一节中的dex反编译 使用DexClassLoader类动态加载插件dex   利用jadx对dex进行反编译可以看到有哪些类 源码分析 BaseDexClassLoader 从BaseDexClassLoader类加载器开始分析 在BaseDexClassLoade…...

从WWDC看苹果产品发展的规律

WWDC 是苹果公司一年一度面向全球开发者的盛会&#xff0c;其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具&#xff0c;对过去十年 WWDC 主题演讲内容进行了系统化分析&#xff0c;形成了这份…...

在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:

在 HarmonyOS 应用开发中&#xff0c;手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力&#xff0c;既支持点击、长按、拖拽等基础单一手势的精细控制&#xff0c;也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档&#xff0c…...

可靠性+灵活性:电力载波技术在楼宇自控中的核心价值

可靠性灵活性&#xff1a;电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中&#xff0c;电力载波技术&#xff08;PLC&#xff09;凭借其独特的优势&#xff0c;正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据&#xff0c;无需额外布…...

cf2117E

原题链接&#xff1a;https://codeforces.com/contest/2117/problem/E 题目背景&#xff1a; 给定两个数组a,b&#xff0c;可以执行多次以下操作&#xff1a;选择 i (1 < i < n - 1)&#xff0c;并设置 或&#xff0c;也可以在执行上述操作前执行一次删除任意 和 。求…...

【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】

1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件&#xff08;System Property Definition File&#xff09;&#xff0c;用于声明和管理 Bluetooth 模块相…...

DBAPI如何优雅的获取单条数据

API如何优雅的获取单条数据 案例一 对于查询类API&#xff0c;查询的是单条数据&#xff0c;比如根据主键ID查询用户信息&#xff0c;sql如下&#xff1a; select id, name, age from user where id #{id}API默认返回的数据格式是多条的&#xff0c;如下&#xff1a; {&qu…...

CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云

目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...

LeetCode - 199. 二叉树的右视图

题目 199. 二叉树的右视图 - 力扣&#xff08;LeetCode&#xff09; 思路 右视图是指从树的右侧看&#xff0c;对于每一层&#xff0c;只能看到该层最右边的节点。实现思路是&#xff1a; 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...

HarmonyOS运动开发:如何用mpchart绘制运动配速图表

##鸿蒙核心技术##运动开发##Sensor Service Kit&#xff08;传感器服务&#xff09;# 前言 在运动类应用中&#xff0c;运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据&#xff0c;如配速、距离、卡路里消耗等&#xff0c;用户可以更清晰…...

基于 TAPD 进行项目管理

起因 自己写了个小工具&#xff0c;仓库用的Github。之前在用markdown进行需求管理&#xff0c;现在随着功能的增加&#xff0c;感觉有点难以管理了&#xff0c;所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD&#xff0c;需要提供一个企业名新建一个项目&#…...