OFA英文图像描述镜像教程:如何将生成结果同步至Elasticsearch构建语义检索库
OFA英文图像描述镜像教程如何将生成结果同步至Elasticsearch构建语义检索库1. 引言你有没有遇到过这样的场景电脑里存了几千张产品图片、设计稿或者生活照片想找一张“一个女孩在沙滩上拿着红色气球”的照片却只能靠记忆在文件夹里翻来翻去或者用“beach.jpg”这种模糊的文件名来搜索结果往往不尽如人意。传统的图片管理方式无论是按文件夹分类还是用简单的文件名标记都很难满足我们对图片内容进行精准检索的需求。图片里丰富的视觉信息——人物、动作、场景、颜色、物体之间的关系——都被锁在了像素里无法被搜索引擎理解。这就是图像描述技术大显身手的地方。想象一下如果每张图片都能自动生成一段文字描述比如“一只橘猫趴在窗台上晒太阳”那么你只需要搜索“橘猫 窗台”就能立刻找到这张照片。这听起来像是未来科技但其实今天你就能自己搭建一套这样的系统。本文将带你一步步实现一个完整的解决方案使用OFA图像描述模型为图片生成英文描述然后将这些描述文本同步到Elasticsearch中构建一个支持语义检索的图片库。整个过程从模型部署到检索应用我都会用最直白的方式讲解即使你是刚接触AI和搜索引擎的新手也能跟着做出来。2. OFA图像描述系统快速部署2.1 系统概览与准备我们先来快速了解一下要用到的核心组件OFA图像描述模型一个专门为图片生成文字描述的AI模型。你给它一张图片它就能输出像“A group of people sitting at a table eating food”这样的英文句子。Elasticsearch一个强大的搜索引擎能够快速检索文本内容。我们将把图片描述存到这里。同步程序连接前两者的桥梁自动把生成的描述送到搜索引擎里。整个流程很简单上传图片 → OFA生成描述 → 保存到Elasticsearch → 用文字搜索图片。在开始之前你需要准备一台Linux服务器Ubuntu 20.04或以上版本比较合适至少8GB内存运行模型和搜索引擎需要一些资源Python 3.8或以上版本基本的命令行操作知识2.2 一键部署OFA服务OFA模型已经打包成了Docker镜像部署起来特别简单。你不需要关心复杂的模型下载和环境配置镜像里都准备好了。首先确保你的服务器上已经安装了Docker和Docker Compose。如果没有安装可以用下面这个命令快速安装以Ubuntu为例# 安装Docker curl -fsSL https://get.docker.com -o get-docker.sh sudo sh get-docker.sh # 安装Docker Compose sudo curl -L https://github.com/docker/compose/releases/download/v2.20.0/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose sudo chmod x /usr/local/bin/docker-compose安装完成后创建一个工作目录然后下载我们的配置文件mkdir ofa-elasticsearch-project cd ofa-elasticsearch-project # 创建docker-compose.yml文件 cat docker-compose.yml EOF version: 3.8 services: ofa-webui: image: csdnmirrors/ofa_image-caption_coco_distilled_en:latest container_name: ofa-webui ports: - 7860:7860 volumes: - ./model_data:/root/.cache/huggingface/hub restart: unless-stopped networks: - ofa-network elasticsearch: image: docker.elastic.co/elasticsearch/elasticsearch:8.11.0 container_name: elasticsearch environment: - discovery.typesingle-node - xpack.security.enabledfalse - ES_JAVA_OPTS-Xms512m -Xmx512m ports: - 9200:9200 volumes: - es_data:/usr/share/elasticsearch/data networks: - ofa-network restart: unless-stopped sync-service: build: ./sync-service container_name: sync-service depends_on: - ofa-webui - elasticsearch environment: - OFA_API_URLhttp://ofa-webui:7860/api/generate - ES_HOSThttp://elasticsearch:9200 volumes: - ./images:/app/images - ./logs:/app/logs networks: - ofa-network restart: unless-stopped networks: ofa-network: driver: bridge volumes: es_data: EOF接着创建同步服务的代码目录和文件# 创建同步服务目录 mkdir -p sync-service # 创建同步服务的Dockerfile cat sync-service/Dockerfile EOF FROM python:3.9-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . . CMD [python, sync_service.py] EOF # 创建依赖文件 cat sync-service/requirements.txt EOF elasticsearch8.11.0 requests2.31.0 watchdog3.0.0 Pillow10.0.0 python-dotenv1.0.0 EOF现在只需要一个命令就能启动所有服务docker-compose up -d等待几分钟让所有容器启动完成。你可以用下面的命令查看服务状态docker-compose ps如果看到三个服务都是“Up”状态就说明部署成功了。2.3 验证服务是否正常打开浏览器访问http://你的服务器IP:7860你应该能看到OFA的Web界面。这个界面很简单就是一个上传图片的按钮和一个结果显示区域。试着上传一张图片比如一张猫的照片。稍等片刻你会看到模型生成的描述比如“A cat sitting on a couch”。同时你也可以验证Elasticsearch是否正常运行curl http://localhost:9200如果返回类似下面的信息说明Elasticsearch也准备好了{ name: your-node-name, cluster_name: docker-cluster, cluster_uuid: xxxxxx, version: { number: 8.11.0 } }3. 构建图片描述同步服务3.1 同步服务的工作原理现在OFA服务和Elasticsearch都跑起来了但它们之间还没有联系。我们需要一个“中间人”来协调它们的工作。这个同步服务要做三件事监控一个指定的文件夹当有新图片放入时立即发现调用OFA服务为图片生成描述把图片信息和描述一起保存到Elasticsearch听起来有点复杂别担心我已经把代码都写好了你只需要复制粘贴就行。3.2 完整的同步服务代码在sync-service目录下创建主程序文件# sync-service/sync_service.py import os import time import json import requests from pathlib import Path from datetime import datetime from watchdog.observers import Observer from watchdog.events import FileSystemEventHandler from elasticsearch import Elasticsearch from PIL import Image import logging # 配置日志 logging.basicConfig( levellogging.INFO, format%(asctime)s - %(name)s - %(levelname)s - %(message)s, handlers[ logging.FileHandler(/app/logs/sync_service.log), logging.StreamHandler() ] ) logger logging.getLogger(__name__) class ImageHandler(FileSystemEventHandler): 处理新图片文件的处理器 def __init__(self, ofa_api_url, es_client, index_nameimage_descriptions): self.ofa_api_url ofa_api_url self.es_client es_client self.index_name index_name self.processed_files set() # 确保Elasticsearch索引存在 self._create_index_if_not_exists() def _create_index_if_not_exists(self): 创建Elasticsearch索引如果不存在 if not self.es_client.indices.exists(indexself.index_name): mapping { mappings: { properties: { image_path: {type: keyword}, filename: {type: keyword}, description: { type: text, analyzer: english }, file_size: {type: long}, image_width: {type: integer}, image_height: {type: integer}, format: {type: keyword}, created_time: {type: date}, processed_time: {type: date}, ofa_response_time: {type: float} } } } self.es_client.indices.create(indexself.index_name, bodymapping) logger.info(f创建索引: {self.index_name}) def on_created(self, event): 当有新文件创建时触发 if not event.is_directory: file_path event.src_path # 只处理图片文件 if self._is_image_file(file_path): # 等待文件完全写入 time.sleep(0.5) self.process_image(file_path) def _is_image_file(self, file_path): 检查文件是否为图片 valid_extensions {.jpg, .jpeg, .png, .gif, .bmp, .webp} return Path(file_path).suffix.lower() in valid_extensions def get_image_description(self, image_path): 调用OFA服务获取图片描述 try: with open(image_path, rb) as f: files {image: f} response requests.post(self.ofa_api_url, filesfiles, timeout30) if response.status_code 200: result response.json() return result.get(description, ), response.elapsed.total_seconds() else: logger.error(fOFA API错误: {response.status_code} - {response.text}) return None, None except Exception as e: logger.error(f调用OFA服务失败: {str(e)}) return None, None def get_image_info(self, image_path): 获取图片基本信息 try: with Image.open(image_path) as img: width, height img.size format img.format file_size os.path.getsize(image_path) return { width: width, height: height, format: format, file_size: file_size } except Exception as e: logger.error(f获取图片信息失败: {str(e)}) return {} def save_to_elasticsearch(self, doc_id, document): 保存文档到Elasticsearch try: response self.es_client.index( indexself.index_name, iddoc_id, documentdocument ) logger.info(f保存到Elasticsearch成功: {doc_id}) return response[result] created except Exception as e: logger.error(f保存到Elasticsearch失败: {str(e)}) return False def process_image(self, image_path): 处理单张图片的完整流程 # 避免重复处理 if image_path in self.processed_files: return logger.info(f开始处理图片: {image_path}) self.processed_files.add(image_path) try: # 1. 获取图片基本信息 image_info self.get_image_info(image_path) if not image_info: return # 2. 调用OFA获取描述 description, response_time self.get_image_description(image_path) if not description: logger.warning(f无法获取图片描述: {image_path}) return logger.info(f图片描述: {description}) # 3. 准备文档数据 doc_id os.path.basename(image_path) _ str(int(time.time())) document { image_path: image_path, filename: os.path.basename(image_path), description: description, file_size: image_info[file_size], image_width: image_info[width], image_height: image_info[height], format: image_info[format], created_time: datetime.fromtimestamp(os.path.getctime(image_path)).isoformat(), processed_time: datetime.now().isoformat(), ofa_response_time: response_time } # 4. 保存到Elasticsearch if self.save_to_elasticsearch(doc_id, document): logger.info(f图片处理完成: {image_path}) else: logger.error(f图片处理失败: {image_path}) except Exception as e: logger.error(f处理图片时出错: {image_path} - {str(e)}) finally: # 处理完成后从集合中移除允许重新处理 self.processed_files.discard(image_path) def main(): 主函数 # 从环境变量获取配置 ofa_api_url os.getenv(OFA_API_URL, http://ofa-webui:7860/api/generate) es_host os.getenv(ES_HOST, http://elasticsearch:9200) watch_directory os.getenv(WATCH_DIR, /app/images) logger.info(fOFA API地址: {ofa_api_url}) logger.info(fElasticsearch地址: {es_host}) logger.info(f监控目录: {watch_directory}) # 创建监控目录如果不存在 Path(watch_directory).mkdir(parentsTrue, exist_okTrue) # 初始化Elasticsearch客户端 es_client Elasticsearch( es_host, request_timeout30 ) # 测试Elasticsearch连接 try: if es_client.ping(): logger.info(Elasticsearch连接成功) else: logger.error(Elasticsearch连接失败) return except Exception as e: logger.error(f连接Elasticsearch失败: {str(e)}) return # 创建事件处理器和观察者 event_handler ImageHandler(ofa_api_url, es_client) observer Observer() observer.schedule(event_handler, watch_directory, recursiveFalse) logger.info(f开始监控目录: {watch_directory}) observer.start() try: # 处理目录中已存在的图片文件 for file_path in Path(watch_directory).iterdir(): if file_path.is_file() and event_handler._is_image_file(str(file_path)): event_handler.process_image(str(file_path)) # 保持程序运行 while True: time.sleep(1) except KeyboardInterrupt: observer.stop() logger.info(服务停止) finally: observer.join() if __name__ __main__: main()3.3 同步服务配置与启动为了让同步服务更灵活我们还可以添加一个配置文件。创建.env文件# sync-service/.env # OFA服务地址如果在同一台服务器可以用ofa-webui:7860 OFA_API_URLhttp://ofa-webui:7860/api/generate # Elasticsearch地址 ES_HOSThttp://elasticsearch:9200 # 监控的图片目录 WATCH_DIR/app/images # 日志级别 LOG_LEVELINFO然后修改sync_service.py的开头部分添加环境变量支持# 在文件开头添加 from dotenv import load_dotenv load_dotenv() # 加载.env文件现在重新启动所有服务# 在项目根目录有docker-compose.yml的目录 docker-compose down docker-compose up -d --build--build参数会重新构建同步服务的镜像确保最新的代码被包含进去。3.4 测试同步功能服务启动后我们来测试一下整个流程是否正常工作。首先在项目根目录下创建images文件夹如果不存在的话mkdir -p images然后找几张测试图片放到这个文件夹里。你可以从网上下载或者用自己的图片。比如下载一张猫的图片# 下载测试图片如果没有wget可以用curl替代 cd images wget https://images.unsplash.com/photo-1514888286974-6d03bde4ba4f -o cat.jpg稍等几秒钟查看同步服务的日志docker-compose logs -f sync-service你应该能看到类似这样的日志sync-service-1 | 2024-01-15 10:30:25 - __main__ - INFO - 开始处理图片: /app/images/cat.jpg sync-service-1 | 2024-01-15 10:30:26 - __main__ - INFO - 图片描述: A cat with green eyes looking at the camera sync-service-1 | 2024-01-15 10:30:26 - __main__ - INFO - 保存到Elasticsearch成功: cat.jpg_1705307426这说明图片已经被成功处理描述也保存到Elasticsearch了。4. 实现语义检索功能4.1 什么是语义检索传统的文本搜索是基于关键词匹配的。比如你搜索“猫”系统会找到所有包含“猫”这个字的描述。但如果你搜索“小动物”或者“宠物”即使描述里没有这些词系统也应该能找到关于猫的图片因为“猫”就是“小动物”和“宠物”。这就是语义检索的威力——它理解词语的含义和关系而不仅仅是字面匹配。Elasticsearch通过内置的文本分析器和评分机制能够实现一定程度的语义搜索。4.2 构建检索API现在数据已经在Elasticsearch里了我们需要一个简单的方式来查询这些数据。创建一个新的Python文件来实现检索API# sync-service/search_api.py from flask import Flask, request, jsonify from elasticsearch import Elasticsearch import os from dotenv import load_dotenv load_dotenv() app Flask(__name__) # 初始化Elasticsearch客户端 es_host os.getenv(ES_HOST, http://elasticsearch:9200) es_client Elasticsearch(es_host, request_timeout30) app.route(/search, methods[GET]) def search_images(): 搜索图片描述 query request.args.get(q, ) size int(request.args.get(size, 10)) if not query: return jsonify({error: 请输入搜索关键词}), 400 try: # 构建搜索请求 search_body { query: { match: { description: { query: query, fuzziness: AUTO # 允许模糊匹配 } } }, sort: [ {_score: {order: desc}} # 按相关性排序 ], size: size } # 执行搜索 response es_client.search( indeximage_descriptions, bodysearch_body ) # 处理结果 results [] for hit in response[hits][hits]: source hit[_source] results.append({ id: hit[_id], score: hit[_score], filename: source[filename], description: source[description], image_path: source[image_path], width: source.get(image_width), height: source.get(image_height), format: source.get(format), processed_time: source.get(processed_time) }) return jsonify({ total: response[hits][total][value], took: response[took], results: results }) except Exception as e: return jsonify({error: str(e)}), 500 app.route(/images, methods[GET]) def list_images(): 列出所有图片分页 page int(request.args.get(page, 1)) size int(request.args.get(size, 20)) try: search_body { query: {match_all: {}}, sort: [{processed_time: {order: desc}}], from: (page - 1) * size, size: size } response es_client.search( indeximage_descriptions, bodysearch_body ) results [] for hit in response[hits][hits]: source hit[_source] results.append({ id: hit[_id], filename: source[filename], description: source[description], processed_time: source.get(processed_time) }) return jsonify({ total: response[hits][total][value], page: page, size: size, results: results }) except Exception as e: return jsonify({error: str(e)}), 500 app.route(/health, methods[GET]) def health_check(): 健康检查 try: if es_client.ping(): return jsonify({status: healthy, elasticsearch: connected}) else: return jsonify({status: unhealthy, elasticsearch: disconnected}), 503 except Exception as e: return jsonify({status: error, message: str(e)}), 500 if __name__ __main__: app.run(host0.0.0.0, port5000, debugTrue)4.3 更新Docker配置我们需要把这个搜索API也加入到Docker Compose中。修改docker-compose.yml添加搜索服务# 在services部分添加 search-api: build: ./sync-service container_name: search-api ports: - 5000:5000 environment: - ES_HOSThttp://elasticsearch:9200 depends_on: - elasticsearch command: python search_api.py networks: - ofa-network restart: unless-stopped同时更新同步服务的Dockerfile确保安装了Flask# sync-service/Dockerfile FROM python:3.9-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt # 添加Flask RUN pip install flask2.3.0 COPY . . # 默认命令还是运行同步服务 CMD [python, sync_service.py]更新requirements.txt# sync-service/requirements.txt elasticsearch8.11.0 requests2.31.0 watchdog3.0.0 Pillow10.0.0 python-dotenv1.0.0 flask2.3.0重新启动所有服务docker-compose down docker-compose up -d --build4.4 测试搜索功能现在搜索API应该已经运行在5000端口了。让我们测试一下# 搜索包含cat的图片 curl http://localhost:5000/search?qcat # 搜索包含animal的图片语义搜索 curl http://localhost:5000/search?qanimal # 列出所有图片 curl http://localhost:5000/images你应该能看到JSON格式的搜索结果。比如搜索cat可能会返回{ total: 1, took: 15, results: [ { id: cat.jpg_1705307426, score: 0.2876821, filename: cat.jpg, description: A cat with green eyes looking at the camera, image_path: /app/images/cat.jpg, width: 1200, height: 800, format: JPEG, processed_time: 2024-01-15T10:30:26.123456 } ] }4.5 简单的Web界面为了让搜索更方便我们可以创建一个简单的HTML界面。在sync-service目录下创建templates文件夹和搜索页面mkdir -p sync-service/templates!-- sync-service/templates/search.html -- !DOCTYPE html html langen head meta charsetUTF-8 meta nameviewport contentwidthdevice-width, initial-scale1.0 title图片语义搜索/title style body { font-family: Arial, sans-serif; max-width: 1200px; margin: 0 auto; padding: 20px; background-color: #f5f5f5; } .header { text-align: center; margin-bottom: 30px; padding: 20px; background: white; border-radius: 10px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); } .search-box { display: flex; gap: 10px; margin-bottom: 20px; } .search-box input { flex: 1; padding: 12px; font-size: 16px; border: 2px solid #ddd; border-radius: 5px; } .search-box button { padding: 12px 24px; background: #007bff; color: white; border: none; border-radius: 5px; cursor: pointer; font-size: 16px; } .search-box button:hover { background: #0056b3; } .results { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 20px; } .image-card { background: white; border-radius: 10px; overflow: hidden; box-shadow: 0 2px 10px rgba(0,0,0,0.1); transition: transform 0.3s; } .image-card:hover { transform: translateY(-5px); } .image-preview { width: 100%; height: 200px; object-fit: cover; } .image-info { padding: 15px; } .image-description { margin: 10px 0; color: #666; line-height: 1.5; } .image-meta { font-size: 12px; color: #999; margin-top: 10px; } .score { display: inline-block; background: #28a745; color: white; padding: 2px 8px; border-radius: 10px; font-size: 12px; margin-right: 10px; } .loading { text-align: center; padding: 40px; display: none; } .error { color: #dc3545; padding: 10px; background: #f8d7da; border-radius: 5px; margin: 10px 0; } /style /head body div classheader h1 图片语义搜索系统/h1 p使用OFA图像描述 Elasticsearch构建的智能图片检索系统/p /div div classsearch-box input typetext idsearchInput placeholder输入关键词搜索图片如cat, animal, person... / button onclicksearchImages()搜索/button /div div idloading classloading p搜索中.../p /div div iderror classerror styledisplay: none;/div div idresultsInfo stylemargin-bottom: 20px;/div div idresults classresults/div script async function searchImages() { const query document.getElementById(searchInput).value.trim(); if (!query) { showError(请输入搜索关键词); return; } // 显示加载中 document.getElementById(loading).style.display block; document.getElementById(error).style.display none; document.getElementById(results).innerHTML ; document.getElementById(resultsInfo).innerHTML ; try { const response await fetch(/search?q${encodeURIComponent(query)}); const data await response.json(); if (response.ok) { displayResults(data); } else { showError(data.error || 搜索失败); } } catch (error) { showError(网络错误: error.message); } finally { document.getElementById(loading).style.display none; } } function displayResults(data) { const resultsDiv document.getElementById(results); const infoDiv document.getElementById(resultsInfo); infoDiv.innerHTML p找到 strong${data.total}/strong 个结果耗时 ${data.took}ms/p ; if (data.results.length 0) { resultsDiv.innerHTML p没有找到相关图片/p; return; } let html ; data.results.forEach(item { // 构建图片URL假设图片可以通过/files/路径访问 const imageUrl /files/${encodeURIComponent(item.filename)}; html div classimage-card img src${imageUrl} alt${item.description} classimage-preview onerrorthis.srchttps://via.placeholder.com/300x200?textImageNotFound div classimage-info div span classscore相关度: ${item.score.toFixed(4)}/span span classimage-meta${item.width}×${item.height}/span /div p classimage-description${item.description}/p div classimage-meta 文件: ${item.filename}br 时间: ${new Date(item.processed_time).toLocaleString()} /div /div /div ; }); resultsDiv.innerHTML html; } function showError(message) { const errorDiv document.getElementById(error); errorDiv.textContent message; errorDiv.style.display block; } // 支持按回车搜索 document.getElementById(searchInput).addEventListener(keypress, function(e) { if (e.key Enter) { searchImages(); } }); // 页面加载时显示所有图片 window.onload async function() { try { const response await fetch(/images?size12); const data await response.json(); if (response.ok) { // 将数据格式化为搜索结果格式 const searchData { total: data.total, took: 0, results: data.results.map(item ({ ...item, score: 1.0, width: 300, height: 200, image_path: /files/${item.filename} })) }; displayResults(searchData); } } catch (error) { console.log(加载图片列表失败:, error); } }; /script /body /html然后更新搜索API添加这个页面的路由和文件服务# 在search_api.py中添加 from flask import render_template, send_from_directory import os # 添加静态文件路由 app.route(/) def index(): return render_template(search.html) app.route(/files/path:filename) def serve_file(filename): 提供图片文件访问 images_dir os.getenv(WATCH_DIR, /app/images) return send_from_directory(images_dir, filename)最后更新Docker Compose配置将图片目录挂载到搜索服务search-api: build: ./sync-service container_name: search-api ports: - 5000:5000 environment: - ES_HOSThttp://elasticsearch:9200 - WATCH_DIR/app/images volumes: - ./images:/app/images # 挂载图片目录 depends_on: - elasticsearch command: python search_api.py networks: - ofa-network restart: unless-stopped重新启动服务docker-compose down docker-compose up -d --build现在访问http://你的服务器IP:5000就能看到一个完整的图片搜索界面了5. 总结5.1 回顾与成果通过这个教程我们成功搭建了一个完整的图像描述和语义检索系统。让我们回顾一下都实现了什么OFA图像描述服务能够自动为上传的图片生成准确的英文描述自动同步服务监控指定文件夹自动处理新图片并保存描述到搜索引擎Elasticsearch存储所有图片描述都被高效地索引和存储语义搜索API提供基于含义的图片搜索功能友好的Web界面让搜索变得简单直观这个系统的价值在于它把非结构化的图片数据转换成了结构化的文本描述让图片内容变得可搜索。无论是个人照片管理、电商商品检索还是内容创作素材库都能从中受益。5.2 实际应用建议在实际使用中你可以根据需求调整和优化性能优化如果图片很多可以考虑批量处理而不是单张处理Elasticsearch可以配置更多节点来提高搜索性能可以为描述字段添加更多的分析器支持多语言搜索功能扩展添加图片分类标签支持按类别筛选实现相似图片搜索基于描述向量添加用户管理支持多用户图片库集成到现有系统中比如CMS、电商平台等运维建议定期备份Elasticsearch数据监控服务运行状态设置告警考虑使用Nginx做反向代理提高安全性5.3 遇到的常见问题在实践过程中你可能会遇到一些问题这里提供一些解决方案问题1OFA服务响应慢检查服务器资源CPU、内存是否充足考虑使用GPU加速推理调整批量处理大小问题2描述不够准确OFA模型主要针对通用场景专业领域图片可能需要微调可以尝试其他图像描述模型或组合多个模型添加后处理对描述进行修正和优化问题3搜索效果不理想调整Elasticsearch的评分参数尝试不同的文本分析器考虑使用更高级的语义搜索技术如向量搜索5.4 下一步探索这个系统只是一个起点还有很多可以探索的方向多模型集成除了OFA还可以集成其他图像描述模型选择最合适的描述多语言支持将英文描述翻译成其他语言支持多语言搜索智能标签自动为图片打上分类标签人物、风景、动物等相似图片搜索基于图片特征向量实现“以图搜图”移动端应用开发手机App随时上传和搜索图片最重要的是这个系统展示了AI技术与传统搜索引擎结合的巨大潜力。通过将AI的理解能力与搜索引擎的检索能力相结合我们能够构建出真正智能的内容管理系统。现在你可以开始上传自己的图片体验语义搜索的便利了。无论是整理旅行照片还是管理设计素材这个系统都能帮你快速找到想要的图片。试试搜索“sunset”、“people smiling”或者“food”看看效果如何吧获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。