news 2026/10/19 23:12:15

Banana Vision Studio自动化测试:Python脚本开发

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Banana Vision Studio自动化测试:Python脚本开发

Banana Vision Studio自动化测试:Python脚本开发

如果你正在用Banana Vision Studio做产品拆解图,有没有想过一个问题:每次更新模型或者调整参数后,怎么确保生成的效果还是稳定的?

我最近就遇到了这个麻烦。团队更新了一个小版本,结果生成的爆炸图里,有几个零件的标注箭头位置全乱了。客户那边等着要图,这边却要重新检查几十张图,那叫一个手忙脚乱。

后来我们痛定思痛,决定搞一套自动化测试体系。现在每次更新,跑一遍脚本就知道有没有问题,心里踏实多了。今天我就把这套方法分享给你,让你也能轻松搞定Banana Vision Studio的质量稳定性。

1. 为什么需要自动化测试?

你可能觉得,Banana Vision Studio就是个生成图片的工具,手动测测不就行了?刚开始我也这么想,但实际用下来,手动测试有几个大问题:

时间成本太高:一张复杂的工业拆解图,从上传参考图到生成结果,少说也要一两分钟。测个十几种场景,半小时就没了。要是测几十种,半天时间就搭进去了。

容易遗漏:今天测了A功能,明天更新了B功能,你可能会忘记再测A。结果就是,新功能没问题,老功能却出了bug。

结果不稳定:人工判断“这张图好不好”,主观性太强。你觉得箭头位置偏了一点没关系,我觉得必须精确到像素。没有统一标准,团队内部都容易扯皮。

回归测试困难:每次更新后,要把所有功能重新测一遍,这个工作量想想都头疼。很多人就偷懒只测新功能,结果就是老bug时不时冒出来。

自动化测试就是为了解决这些问题。写一次脚本,以后每次更新一键运行,几分钟内就能知道这次更新有没有引入新问题。更重要的是,它能给出客观的测试结果,减少人为判断的误差。

2. 环境准备与基础框架搭建

2.1 Python环境配置

首先确保你的Python环境是3.8或以上版本。我推荐用虚拟环境,这样不同项目的依赖不会互相干扰。

# 创建虚拟环境 python -m venv banana_test_env # 激活虚拟环境 # Windows banana_test_env\Scripts\activate # Mac/Linux source banana_test_env/bin/activate # 安装必要依赖 pip install requests pillow opencv-python numpy pytest

如果你用的是CSDN星图平台部署的Banana Vision Studio,还需要安装对应的SDK:

# 安装星图平台SDK pip install csdn-ai-sdk

2.2 项目结构规划

一个好的项目结构能让后续维护轻松很多。我建议这样组织:

banana_vision_tests/ ├── tests/ # 测试用例目录 │ ├── __init__.py │ ├── test_basic.py # 基础功能测试 │ ├── test_quality.py # 质量测试 │ └── test_performance.py # 性能测试 ├── utils/ # 工具函数 │ ├── __init__.py │ ├── api_client.py # API封装 │ └── image_utils.py # 图片处理工具 ├── config/ # 配置文件 │ └── settings.py ├── data/ # 测试数据 │ ├── input_images/ # 输入图片 │ └── expected_results/ # 预期结果 ├── reports/ # 测试报告 ├── requirements.txt # 依赖列表 └── run_tests.py # 测试运行入口

2.3 基础测试框架选择

Python里测试框架很多,我推荐用unittest,因为它是Python标准库自带的,不需要额外安装,而且功能足够强大。

如果你需要更灵活的测试,也可以考虑pytest。不过对于Banana Vision Studio这种API测试,unittest完全够用。

3. 核心测试用例设计与实现

3.1 API连接测试

这是最基础的测试,确保我们能正常连接到Banana Vision Studio服务。

import unittest import requests import time from utils.api_client import BananaVisionClient class TestAPIConnection(unittest.TestCase): """测试API连接基础功能""" def setUp(self): """每个测试用例执行前的准备工作""" # 从配置文件读取API配置 self.client = BananaVisionClient( api_key="your_api_key_here", base_url="https://your-banana-vision-endpoint.com" ) # 准备测试图片 self.test_image_path = "data/input_images/test_product.jpg" def test_api_health_check(self): """测试API健康状态""" try: response = self.client.health_check() self.assertEqual(response.status_code, 200) self.assertIn("status", response.json()) self.assertEqual(response.json()["status"], "healthy") print(" API健康检查通过") except Exception as e: self.fail(f"API健康检查失败: {str(e)}") def test_basic_image_upload(self): """测试图片上传功能""" try: # 上传图片并获取任务ID task_id = self.client.upload_image(self.test_image_path) self.assertIsNotNone(task_id) self.assertTrue(len(task_id) > 10) # 任务ID应该有足够长度 # 等待处理完成 max_wait_time = 60 # 最大等待60秒 wait_interval = 2 # 每2秒检查一次 for _ in range(max_wait_time // wait_interval): status = self.client.get_task_status(task_id) if status == "completed": break elif status == "failed": self.fail("图片处理失败") time.sleep(wait_interval) else: self.fail("处理超时") # 获取处理结果 result = self.client.get_result(task_id) self.assertIsNotNone(result) self.assertIn("image_url", result) print(" 基础图片上传测试通过") except Exception as e: self.fail(f"图片上传测试失败: {str(e)}") def test_invalid_image_format(self): """测试无效图片格式处理""" # 创建一个无效的图片文件 invalid_image_path = "data/input_images/invalid.txt" with open(invalid_image_path, "w") as f: f.write("This is not an image") try: task_id = self.client.upload_image(invalid_image_path) # 如果上传成功,检查任务状态应该是失败 if task_id: status = self.client.get_task_status(task_id) self.assertEqual(status, "failed") print(" 无效图片格式处理测试通过") except requests.exceptions.HTTPError as e: # 或者API直接返回错误 self.assertEqual(e.response.status_code, 400) print(" 无效图片格式处理测试通过(API正确拒绝)")

3.2 生成质量测试

对于Banana Vision Studio来说,生成图片的质量是最关键的。我们需要测试生成的拆解图是否满足要求。

import cv2 import numpy as np from PIL import Image class TestGenerationQuality(unittest.TestCase): """测试生成质量""" def test_exploded_view_accuracy(self): """测试爆炸图准确性""" # 准备输入图片和预期结果 input_image = "data/input_images/mechanical_part.jpg" expected_result = "data/expected_results/exploded_view.png" # 调用API生成爆炸图 result = self.client.generate_exploded_view( image_path=input_image, style="technical_illustration", detail_level="high" ) # 保存生成结果 generated_image = "reports/generated_exploded_view.png" result.save(generated_image) # 对比生成结果和预期结果 similarity = self.compare_images(generated_image, expected_result) # 相似度应该达到一定阈值 self.assertGreaterEqual(similarity, 0.85, f"图片相似度不足: {similarity:.2f}") print(f" 爆炸图准确性测试通过,相似度: {similarity:.2f}") def test_label_position_accuracy(self): """测试标注位置准确性""" # 生成带标注的拆解图 result = self.client.generate_labeled_diagram( image_path="data/input_images/electronic_device.jpg", label_style="arrow_with_text" ) # 使用OpenCV检测箭头和文字位置 image = cv2.imread("reports/generated_labeled.png") gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 检测箭头(使用模板匹配或特征检测) arrow_positions = self.detect_arrows(gray) # 检查箭头数量 self.assertGreaterEqual(len(arrow_positions), 5, "标注箭头数量不足") # 检查箭头分布是否均匀 positions_array = np.array(arrow_positions) x_std = np.std(positions_array[:, 0]) y_std = np.std(positions_array[:, 1]) # 标准差不能太大,说明分布不能太集中 self.assertLess(x_std, image.shape[1] * 0.3, "箭头X方向分布不均匀") self.assertLess(y_std, image.shape[0] * 0.3, "箭头Y方向分布不均匀") print(f" 标注位置测试通过,检测到{len(arrow_positions)}个箭头") def compare_images(self, img1_path, img2_path, threshold=0.8): """比较两张图片的相似度""" # 使用结构相似性指数(SSIM) from skimage.metrics import structural_similarity as ssim img1 = cv2.imread(img1_path) img2 = cv2.imread(img2_path) # 调整到相同尺寸 if img1.shape != img2.shape: img2 = cv2.resize(img2, (img1.shape[1], img1.shape[0])) # 转换为灰度图 gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY) gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY) # 计算SSIM score, _ = ssim(gray1, gray2, full=True) return score def detect_arrows(self, gray_image): """检测图片中的箭头""" # 使用边缘检测 edges = cv2.Canny(gray_image, 50, 150) # 使用霍夫变换检测直线 lines = cv2.HoughLinesP(edges, 1, np.pi/180, threshold=50, minLineLength=30, maxLineGap=10) arrow_positions = [] if lines is not None: for line in lines: x1, y1, x2, y2 = line[0] # 计算线段中点作为箭头位置 mid_x = (x1 + x2) // 2 mid_y = (y1 + y2) // 2 arrow_positions.append((mid_x, mid_y)) return arrow_positions

3.3 性能与稳定性测试

除了功能正确性,我们还需要关注性能和稳定性。

import time import statistics class TestPerformanceAndStability(unittest.TestCase): """测试性能与稳定性""" def test_response_time(self): """测试响应时间""" test_cases = [ ("small_image.jpg", "简单产品"), ("medium_complexity.jpg", "中等复杂度"), ("high_complexity.jpg", "高复杂度") ] response_times = [] for image_file, description in test_cases: image_path = f"data/input_images/{image_file}" start_time = time.time() result = self.client.generate_exploded_view( image_path=image_path, style="technical_illustration" ) end_time = time.time() response_time = end_time - start_time response_times.append(response_time) print(f"{description}响应时间: {response_time:.2f}秒") # 单次测试的响应时间要求 if "高复杂度" in description: self.assertLess(response_time, 120, "高复杂度图片处理超时") elif "中等复杂度" in description: self.assertLess(response_time, 60, "中等复杂度图片处理超时") else: self.assertLess(response_time, 30, "简单图片处理超时") # 计算平均响应时间 avg_time = statistics.mean(response_times) print(f" 平均响应时间: {avg_time:.2f}秒") def test_concurrent_requests(self): """测试并发请求处理能力""" import threading results = [] errors = [] def make_request(request_id): """单个请求线程""" try: start_time = time.time() result = self.client.generate_exploded_view( image_path="data/input_images/test_product.jpg", style="technical_illustration" ) end_time = time.time() results.append({ "id": request_id, "time": end_time - start_time, "success": True }) except Exception as e: errors.append({ "id": request_id, "error": str(e) }) # 创建5个并发线程 threads = [] for i in range(5): thread = threading.Thread(target=make_request, args=(i,)) threads.append(thread) thread.start() # 等待所有线程完成 for thread in threads: thread.join() # 检查结果 self.assertEqual(len(errors), 0, f"并发请求出现错误: {errors}") self.assertEqual(len(results), 5, "并发请求数量不符") # 检查响应时间差异不能太大 response_times = [r["time"] for r in results] time_std = statistics.stdev(response_times) self.assertLess(time_std, 10.0, "并发请求响应时间差异过大") print(f" 并发测试通过,5个请求平均时间: {statistics.mean(response_times):.2f}秒") def test_long_running_stability(self): """测试长时间运行的稳定性""" total_requests = 20 successful_requests = 0 for i in range(total_requests): try: # 交替使用不同的生成模式 if i % 3 == 0: result = self.client.generate_exploded_view( image_path="data/input_images/test_product.jpg", style="technical_illustration" ) elif i % 3 == 1: result = self.client.generate_labeled_diagram( image_path="data/input_images/test_product.jpg", label_style="arrow_with_text" ) else: result = self.client.generate_cutaway_view( image_path="data/input_images/test_product.jpg", cut_plane="vertical" ) successful_requests += 1 print(f"请求 {i+1}/{total_requests} 成功") # 每5个请求休息一下,模拟真实使用场景 if (i + 1) % 5 == 0: time.sleep(2) except Exception as e: print(f"请求 {i+1} 失败: {str(e)}") success_rate = successful_requests / total_requests self.assertGreaterEqual(success_rate, 0.9, f"稳定性测试成功率不足: {success_rate:.2%}") print(f" 稳定性测试通过,成功率: {success_rate:.2%}")

4. 高级功能与异常处理

4.1 参数边界测试

测试各种参数组合的边界情况,确保API能够正确处理。

class TestParameterBoundaries(unittest.TestCase): """测试参数边界情况""" def test_style_parameter_variations(self): """测试不同风格参数""" styles = [ "technical_illustration", "exploded_view", "cutaway", "schematic", "photorealistic" ] for style in styles: try: result = self.client.generate_diagram( image_path="data/input_images/test_product.jpg", style=style, detail_level="medium" ) self.assertIsNotNone(result) print(f" 风格 '{style}' 测试通过") except Exception as e: # 如果API不支持某种风格,应该明确返回错误 self.assertIn("unsupported style", str(e).lower()) print(f" 风格 '{style}' 不被支持(符合预期)") def test_detail_level_boundaries(self): """测试细节级别边界""" # 测试有效的细节级别 valid_levels = ["low", "medium", "high", "ultra"] for level in valid_levels: result = self.client.generate_diagram( image_path="data/input_images/test_product.jpg", style="technical_illustration", detail_level=level ) self.assertIsNotNone(result) # 测试无效的细节级别 invalid_levels = ["", "invalid", "最高", None] for level in invalid_levels: try: result = self.client.generate_diagram( image_path="data/input_images/test_product.jpg", style="technical_illustration", detail_level=level ) # 如果执行到这里,说明API没有正确验证参数 self.fail(f"无效参数 '{level}' 应该被拒绝") except Exception as e: # 期望API返回参数错误 self.assertIn("invalid", str(e).lower()) def test_image_size_limits(self): """测试图片大小限制""" # 测试过小的图片 small_image = self.create_test_image(100, 100) # 100x100像素 try: result = self.client.generate_diagram( image_data=small_image, style="technical_illustration" ) # 有些API可能支持小图,有些可能拒绝 # 这里我们只记录,不强制失败 print(" 小尺寸图片被接受") except Exception as e: print(f" 小尺寸图片被正确拒绝: {str(e)}") # 测试过大的图片(需要根据API限制调整) large_image = self.create_test_image(10000, 10000) # 可能超限 try: result = self.client.generate_diagram( image_data=large_image, style="technical_illustration" ) print(" 大尺寸图片被接受") except Exception as e: print(f" 大尺寸图片被正确拒绝: {str(e)}") def create_test_image(self, width, height): """创建测试图片""" from PIL import Image, ImageDraw image = Image.new('RGB', (width, height), color='white') draw = ImageDraw.Draw(image) # 画一个简单的矩形,让图片有点内容 draw.rectangle([10, 10, width-10, height-10], outline='black', width=2) return image

4.2 错误处理与恢复

良好的错误处理能让测试更加健壮。

class TestErrorHandling(unittest.TestCase): """测试错误处理机制""" def test_network_timeout_handling(self): """测试网络超时处理""" # 创建一个会超时的客户端(设置很短的超时时间) timeout_client = BananaVisionClient( api_key="test_key", base_url="https://your-banana-vision-endpoint.com", timeout=0.1 # 0.1秒超时,几乎肯定会超时 ) try: result = timeout_client.generate_diagram( image_path="data/input_images/test_product.jpg" ) self.fail("应该触发超时错误") except requests.exceptions.Timeout: print(" 网络超时被正确捕获") except Exception as e: # 其他类型的错误也可以接受 print(f" 错误被捕获: {type(e).__name__}") def test_rate_limit_handling(self): """测试速率限制处理""" # 快速发送多个请求,触发速率限制 errors_count = 0 for i in range(20): # 发送20个快速请求 try: result = self.client.generate_diagram( image_path="data/input_images/test_product.jpg" ) time.sleep(0.1) # 稍微休息一下 except requests.exceptions.HTTPError as e: if e.response.status_code == 429: # Too Many Requests errors_count += 1 print(f"请求 {i+1} 被速率限制") # 遇到速率限制后等待一段时间 time.sleep(2) else: raise # 应该至少触发一次速率限制 self.assertGreater(errors_count, 0, "应该触发速率限制") print(f" 速率限制处理测试通过,触发 {errors_count} 次限制") def test_invalid_api_key(self): """测试无效API密钥处理""" invalid_client = BananaVisionClient( api_key="invalid_key_123456", base_url="https://your-banana-vision-endpoint.com" ) try: result = invalid_client.generate_diagram( image_path="data/input_images/test_product.jpg" ) self.fail("无效API密钥应该被拒绝") except requests.exceptions.HTTPError as e: self.assertEqual(e.response.status_code, 401) # Unauthorized print(" 无效API密钥被正确拒绝") def test_service_unavailable(self): """测试服务不可用时的处理""" # 使用一个不存在的端点 unavailable_client = BananaVisionClient( api_key="test_key", base_url="https://nonexistent-endpoint-12345.com" ) try: result = unavailable_client.generate_diagram( image_path="data/input_images/test_product.jpg" ) self.fail("应该无法连接到服务") except requests.exceptions.ConnectionError: print(" 服务不可用错误被正确捕获") except Exception as e: print(f" 连接错误被捕获: {type(e).__name__}")

5. 测试报告与持续集成

5.1 生成详细测试报告

测试不仅要能运行,还要能生成清晰的报告。

import json import datetime from html import escape class TestReporter: """测试报告生成器""" def __init__(self): self.results = [] self.start_time = None self.end_time = None def start_test_run(self): """开始测试运行""" self.start_time = datetime.datetime.now() print(f" 测试开始于: {self.start_time}") def add_test_result(self, test_name, status, message="", details=None): """添加测试结果""" result = { "test_name": test_name, "status": status, # "passed", "failed", "skipped", "error" "message": message, "timestamp": datetime.datetime.now().isoformat(), "details": details or {} } self.results.append(result) # 控制台输出 status_icon = "" if status == "passed" else "" if status == "failed" else "" print(f"{status_icon} {test_name}: {message}") def end_test_run(self): """结束测试运行""" self.end_time = datetime.datetime.now() duration = self.end_time - self.start_time # 统计结果 total = len(self.results) passed = sum(1 for r in self.results if r["status"] == "passed") failed = sum(1 for r in self.results if r["status"] == "failed") print(f"\n 测试完成!") print(f" 总测试数: {total}") print(f" 通过: {passed}") print(f" 失败: {failed}") print(f" 耗时: {duration.total_seconds():.2f}秒") # 生成报告文件 self.generate_html_report() self.generate_json_report() def generate_html_report(self): """生成HTML格式的测试报告""" html_content = f""" <!DOCTYPE html> <html> <head> <title>Banana Vision Studio 测试报告</title> <style> body {{ font-family: Arial, sans-serif; margin: 40px; }} .summary {{ background: #f5f5f5; padding: 20px; border-radius: 5px; margin-bottom: 30px; }} .test-result {{ padding: 10px; margin: 5px 0; border-left: 4px solid; }} .passed {{ border-color: #4CAF50; background: #e8f5e9; }} .failed {{ border-color: #f44336; background: #ffebee; }} .skipped {{ border-color: #ff9800; background: #fff3e0; }} .stats {{ display: flex; gap: 20px; margin-top: 10px; }} .stat-box {{ padding: 10px; border-radius: 5px; text-align: center; min-width: 100px; }} .stat-passed {{ background: #4CAF50; color: white; }} .stat-failed {{ background: #f44336; color: white; }} .stat-total {{ background: #2196F3; color: white; }} </style> </head> <body> <h1>Banana Vision Studio 自动化测试报告</h1> <div class="summary"> <h2>测试概览</h2> <p>测试时间: {self.start_time} 到 {self.end_time}</p> <p>总耗时: {(self.end_time - self.start_time).total_seconds():.2f}秒</p> <div class="stats"> <div class="stat-box stat-total"> <h3>总测试数</h3> <p>{len(self.results)}</p> </div> <div class="stat-box stat-passed"> <h3>通过</h3> <p>{sum(1 for r in self.results if r['status'] == 'passed')}</p> </div> <div class="stat-box stat-failed"> <h3>失败</h3> <p>{sum(1 for r in self.results if r['status'] == 'failed')}</p> </div> </div> </div> <h2>详细测试结果</h2> """ for result in self.results: status_class = result["status"] html_content += f""" <div class="test-result {status_class}"> <h3>{escape(result['test_name'])}</h3> <p>状态: <strong>{result['status'].upper()}</strong></p> <p>时间: {result['timestamp']}</p> <p>信息: {escape(result['message'])}</p> </div> """ html_content += """ </body> </html> """ report_path = f"reports/test_report_{self.start_time.strftime('%Y%m%d_%H%M%S')}.html" with open(report_path, "w", encoding="utf-8") as f: f.write(html_content) print(f"📄 HTML报告已生成: {report_path}") def generate_json_report(self): """生成JSON格式的测试报告""" report_data = { "test_run": { "start_time": self.start_time.isoformat(), "end_time": self.end_time.isoformat(), "duration_seconds": (self.end_time - self.start_time).total_seconds() }, "summary": { "total_tests": len(self.results), "passed": sum(1 for r in self.results if r["status"] == "passed"), "failed": sum(1 for r in self.results if r["status"] == "failed"), "skipped": sum(1 for r in self.results if r["status"] == "skipped") }, "results": self.results } report_path = f"reports/test_report_{self.start_time.strftime('%Y%m%d_%H%M%S')}.json" with open(report_path, "w", encoding="utf-8") as f: json.dump(report_data, f, indent=2, ensure_ascii=False) print(f"📄 JSON报告已生成: {report_path}") # 在测试运行中使用报告器 def run_all_tests(): """运行所有测试并生成报告""" reporter = TestReporter() reporter.start_test_run() # 创建测试套件 loader = unittest.TestLoader() suite = unittest.TestSuite() # 添加测试类 suite.addTests(loader.loadTestsFromTestCase(TestAPIConnection)) suite.addTests(loader.loadTestsFromTestCase(TestGenerationQuality)) suite.addTests(loader.loadTestsFromTestCase(TestPerformanceAndStability)) suite.addTests(loader.loadTestsFromTestCase(TestParameterBoundaries)) suite.addTests(loader.loadTestsFromTestCase(TestErrorHandling)) # 运行测试 runner = unittest.TextTestRunner(verbosity=2) result = runner.run(suite) # 收集结果到报告器 for test_case in suite: # 这里简化处理,实际需要更精细的结果收集 reporter.add_test_result( test_name=str(test_case), status="passed" # 简化处理,实际需要从result对象获取 ) reporter.end_test_run() return result.wasSuccessful()

5.2 集成到持续集成流程

最后,我们可以把测试脚本集成到CI/CD流程中,比如GitHub Actions。

# .github/workflows/banana-vision-tests.yml name: Banana Vision Studio Tests on: push: branches: [ main, develop ] pull_request: branches: [ main ] schedule: # 每天凌晨2点运行一次 - cron: '0 2 * * *' jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Set up Python uses: actions/setup-python@v4 with: python-version: '3.9' - name: Install dependencies run: | python -m pip install --upgrade pip pip install -r requirements.txt pip install pytest coverage - name: Run tests env: BANANA_VISION_API_KEY: ${{ secrets.BANANA_VISION_API_KEY }} BANANA_VISION_BASE_URL: ${{ secrets.BANANA_VISION_BASE_URL }} run: | python run_tests.py - name: Upload test reports if: always() uses: actions/upload-artifact@v3 with: name: test-reports path: reports/ - name: Send notification on failure if: failure() uses: actions/github-script@v6 with: script: | github.rest.issues.create({ owner: context.repo.owner, repo: context.repo.repo, title: '🚨 Banana Vision Studio 测试失败', body: `自动化测试运行失败,请检查最新提交。\n\n查看详细报告:${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}`, labels: ['bug', 'tests'] })

6. 总结

整套自动化测试体系用下来,最大的感受就是心里有底了。以前每次更新都提心吊胆,现在只要跑一遍测试脚本,几分钟就知道这次更新有没有问题。

这套测试方案覆盖了从基础功能到高级特性的各个方面,既有API连接测试确保服务可用,也有生成质量测试保证输出效果,还有性能测试关注响应速度,以及异常处理测试提高系统健壮性。

实际部署时,建议先从核心功能开始,比如爆炸图生成和标注准确性,这些是Banana Vision Studio最核心的功能。然后再逐步补充其他测试用例。测试数据也很重要,要准备一些典型的工业产品图片,覆盖简单到复杂的各种情况。

最后生成的测试报告不仅给开发团队看,也可以给产品经理和客户看,让他们直观地了解系统的稳定性和可靠性。特别是HTML格式的报告,视觉效果很好,适合在项目会议上展示。

如果你也在用Banana Vision Studio做工业拆解图,强烈建议花点时间搭建这样一套自动化测试体系。前期投入一些时间,后期能省下大量的手动测试和问题排查时间,绝对是值得的。


获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/19 23:07:43

小白也能懂:Ollama部署GLM-4.7-Flash全流程

小白也能懂&#xff1a;Ollama部署GLM-4.7-Flash全流程 想要在本地快速体验强大的GLM-4.7-Flash模型吗&#xff1f;不用折腾复杂的环境配置&#xff0c;不用头疼各种依赖问题&#xff0c;通过Ollama一键部署&#xff0c;10分钟就能让这个30B级别的强大模型在你的电脑上跑起来。…

作者头像 李华
网站建设 2026/10/19 23:07:35

Qwen3-4B Instruct-2507入门必看:Qwen3-4B与Phi-3-mini在推理速度对比

Qwen3-4B Instruct-2507入门必看&#xff1a;Qwen3-4B与Phi-3-mini在推理速度对比 1. 项目概述 Qwen3-4B Instruct-2507是阿里通义千问团队推出的纯文本大语言模型&#xff0c;专门针对文本处理场景进行了深度优化。这个版本移除了视觉相关的冗余模块&#xff0c;专注于代码编…

作者头像 李华
网站建设 2026/10/19 23:06:08

Qwen3-Reranker-0.6B实战教程:与LlamaIndex NodePostprocessor集成指南

Qwen3-Reranker-0.6B实战教程&#xff1a;与LlamaIndex NodePostprocessor集成指南 1. 引言&#xff1a;为什么需要语义重排序&#xff1f; 在构建RAG&#xff08;检索增强生成&#xff09;系统时&#xff0c;很多开发者都会遇到这样的问题&#xff1a;用向量数据库检索出来的…

作者头像 李华
网站建设 2026/10/7 9:58:31

Pi0高性能部署:基于CUDA的GPU加速实践

Pi0高性能部署&#xff1a;基于CUDA的GPU加速实践 1. 引言 如果你正在使用Pi0这样的视觉-语言-动作模型&#xff0c;可能会遇到推理速度不够快的问题。特别是在需要实时控制的机器人应用中&#xff0c;每秒钟几十帧的处理要求对计算性能提出了很高挑战。 今天我要分享的是如…

作者头像 李华
网站建设 2026/10/5 19:10:55

可能是 Python 中展示多对多比例关系的最佳数据可视化

原文&#xff1a;towardsdatascience.com/probably-the-best-data-visualisation-for-showing-many-to-many-proportion-in-python-40bdd24365d5 https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/418d682afff47161768043287f3174c0.png 在…

作者头像 李华