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

Spring with AI (): 搜索扩展——向量数据库与RAG(下)谋

. GIF文件结构相比于 WAV 文件的简单粗暴GIF 的结构要精密得多因为它天生是为了网络传输而设计的包含了压缩机制。当我们用二进制视角观察 GIF 时它是由一个个 数据块Block 组成的数据块 (Block Name) 中文名称 字节数 (Bytes) 作用与核心逻辑Header 头标识 6 一般为 GIF89a当然也有GIF87a,用于声明这是一个GIF文件采用xx标准。Logical Screen Descriptor 逻辑屏幕描述符 7 画布设定定义图像总宽高、背景色索引及是否使用全局调色板。Global Color Table 全局颜色表 3 × N 颜料盘存储 RGB 颜色如 00 FF 00N 为颜色数最大256。 默认使用RGB颜色时每个颜色均采用3个字节存储Application Extension 应用程序扩展 19 (通常) 最常用的是 Netscape 扩展用于“循环播放次数”。Graphic Control Extension 图形控制扩展 8 播放控制定义每一帧的延迟时间动画快慢和透明色。Image Descriptor 图像描述符 10 帧属性定义当前这一帧在画布上的位置x, y和尺寸。Image Data 图像数据 可变 用处如其名Trailer 结束标识 1 终点固定为 0x3B (分号)标志文件彻底结束。其中最重要的就是图像数据了其他的块用于规定这些图像数据应当如何呈现到我们眼中或是告知文件的开始结束因此对于我们来说其他块基本上都有固定模板只有图像数据需要我们自己定义。2.LZW-GIF强制使用的图像压缩算法搞定了GIF的文件结构接下来就需要我们解决另一个拦路虎LZW——一个经典的无损图像压缩算法为了解决他我们可以从他的原理入手。LZW通过为复杂数据构建简单索引来减少存储的数据量这一点是朴素的哈希算法当然这一算法的发明者通过一套特殊的规则使得其他人可以直接通过索引数据反推出复杂数据而在GIF中则是GIF发明公司将他所规定的规则写好编写GIF的人根据这一套规则构建数据然后其他人直接使用套用了这一套规则的解码器解码便能将数据还原成原来的样子。GIF的解码器又是如何读取数据的呢解码器初始时一次性读取9位数据然后从字典中添加这一对应关系根据GIF规范一旦字典里的条目达到 512 个解码器就会自动将读取位宽从 9 位增加到 10 位。如果我们直接存放数据那么结果就是数据读取错位解码出来的内容就会与我们想象中的不一样如果我们想要让他的数据读取正常通常做法就是我们构建一个同步状态机即模拟GIF解码器读取数据的过程写入数据构建一个字典以相同的标准增加写入位宽从而让解码器读取时能正确读取。但是这一过程看着就十分繁琐能不能用一个简单的方法来让解码器正常读取数据呢3.解决方案GIF 协议中有一个特殊的指令叫 Clear Code清除代码值为256。它的作用是告诉解码器“嘿把之前的字典都忘了吧我们重新开始。”利用这一点我们可以在代码中采用了一种偷鸡的策略我们不尝试去寻找复杂的重复模式。我们每写入一小段像素例如 125 个就立刻发送一个 Clear Code。这强制让 LZW 字典始终处于“初始状态”。在初始状态下LZW 的编码就等同于直接输出像素的颜色索引值。现在让我们来实现他4. 构建3d立方体在上一篇关于 3D 本质的文章中我们推导出了两个核心公式。在这个程序中我们将直接把它们转化为 C 代码。旋转公式为了让立方体动起来我们需要每一帧都改变顶点的坐标。这里使用旋转矩阵的简化版Point3D rotate(Point3D p, float angle) {// 绕 Y 轴旋转float nx p.x * cos(angle) - p.z * sin(angle);float nz p.x * sin(angle) p.z * cos(angle);// 绕 X 轴微调旋转让旋转看起来更立体float ny p.y * cos(angle * 0.8f) - nz * sin(angle * 0.8f);nz p.y * sin(angle * 0.8f) nz * cos(angle * 0.8f);return {nx, ny, nz};}投影公式透视如何把 3D 坐标变成屏幕上的像素点记得那个核心法则吗“近大远小本质就是除以 Z”。pair project(Point3D p, int W, int H) {float fov 160.0f; // 视野系数float viewer_dist 4.0f; // 眼睛离物体的距离// 核心逻辑除以 (z dist)float factor fov / (viewer_dist p.z);return { (int)(p.x * factor W / 2), (int)(p.y * factor H / 2) };}有了这两个函数我们就能在内存里的一个二维数组vector pixels上画线了。手写 GIF 编码器我们实现了一个极简的编码器struct GifBitStream。它的工作是把像素点的颜色索引0或1打包成变长的二进制码流。// GIF 的数据存储不仅是字节还需要处理“位操作”// 比如写入一个 9-bit 的代码可能跨越两个字节struct GifBitStream {vector byteData;u32 bitBuffer 0;int bitCount 0;void writeCode(u32 code, int size) {// 将数据移位并存入缓冲区...// 凑够8位就写入 byteData}// ...};特别说明绕过LZW的问题生成的GIF没有压缩体积较为大4. 完整代码下面是完整的 C 代码计算旋转 3D 点 - 投影成 2D 点。绘图在内存的黑板上画线Bresenham 直线算法。编码将内存的黑板按照 GIF 协议压缩并写入文件。(代码较长建议直接复制编译运行感受生成的快感)#includeusing namespace std;#define u8 uint8_t#define u16 uint16_t#define u32 uint32_tstruct Point3D {float x, y, z;};struct Edge {int u, v;};Point3D rotate(Point3D p, float angle) {float nx p.x * cos(angle) - p.z * sin(angle);float nz p.x * sin(angle) p.z * cos(angle);float ny p.y * cos(angle * 0.8f) - nz * sin(angle * 0.8f);nz p.y * sin(angle * 0.8f) nz * cos(angle * 0.8f);return {nx, ny, nz};}pair project(Point3D p, int W, int H) {float fov 160.0f;float viewer_dist 4.0f;float factor fov / (viewer_dist p.z);return { (int)(p.x * factor W / 2), (int)(p.y * factor H / 2) };}inline void drawLine(vector buffer, int W, int H, int x0, int y0, int x1, int y1) {int dx abs(x1 - x0), sx x0 x1 ? 1 : -1;int dy -abs(y1 - y0), sy y0 y1 ? 1 : -1;int err dx dy;while (true) {if (x0 0 x0 W y0 0 y0 H) buffer[y0 * W x0] 1;if (x0 x1 y0 y1) break;int e2 2 * err;if (e2 dy) { err dy; x0 sx; }if (e2 dx) { err dx; y0 sy; }}}// --- GIF 二进制协议部分 ---struct GifBitStream {vector byteData;u32 bitBuffer 0;int bitCount 0;// 写入指定位宽的代码inline void writeCode(u32 code, int size) {bitBuffer | (code bitCount);bitCount size;while (bitCount 8) {byteData.push_back(bitBuffer 0xFF);bitBuffer 8;bitCount - 8;}}inline void flush(ofstream f) {if (bitCount 0) byteData.push_back(bitBuffer 0xFF);// GIF 规定数据必须切成每块最大 255 字节的小块for (size_t i 0; i byteData.size(); i 255) {u8 blockSize (u8)min((size_t)255, byteData.size() - i);f.put(blockSize);f.write((char*)byteData[i], blockSize);}f.put(0); // 块结束}};inline void writeWord(ofstream f, u16 v) {f.put(v 0xFF);f.put((v 8) 0xFF);}inline void writeGifFrame(ofstream f, const vector pixels, int W, int H) {// 1. 图形控制扩展 (帧间隔)f.put(0x21);f.put(0xF9);f.put(0x04);f.put(0x09); // 属性还原背景不使用透明writeWord(f, 4); // 延迟 40ms (1/25 FPS)f.put(0);f.put(0);// 2. 图像描述符f.put(0x2C);// 偏移writeWord(f, 0);writeWord(f, 0);// 宽高writeWord(f, W);writeWord(f, H);f.put(0x00);// 3. 数据f.put(0x08); // 8位色GifBitStream stream;const int ClearCode 256; //清空指令const int EOICode 257;stream.writeCode(ClearCode, 9); // 清空解码器字典int pixCount 0;for (u8 p : pixels) {stream.writeCode(p, 9);pixCount;//每 125 个像素重置一次字典保证位宽不变不会提前读取到下一个字节if (pixCount 125) {stream.writeCode(ClearCode, 9);pixCount 0;}}stream.writeCode(EOICode, 9); // 结束stream.flush(f);}signed main(int argc,char* argv[]){const int W 200, H 200;ofstream f(cube_perfect.gif, ios::binary); //以二进制方式写入GIF文件// [Header]f GIF89a;//89a 标准// [Logical Screen Descriptor]writeWord(f, W); writeWord(f, H);f.put(0xF7); // 开启全局调色板 (256色)f.put(0);f.put(0);// [Global Color Table]全局调色板// 0: 背景黑f.put(0);f.put(0);f.put(0);// 1: 极客绿f.put(0);f.put(255);f.put(0);//只用到两种颜色其余填充黑色for(int i 2; i 256; i){f.put(0); f.put(0); f.put(0);}// [Netscape Loop] 循环动画扩展f.put(0x21); // Netscape块标识f.put(0xFF); // 扩展类型标识f.put(0x0B); // 信息长度f NETSCAPE2.0; //应用程序信息f.put(0x03); // 数据长度到结束符前f.put(0x01); //索引writeWord(f, 0); //无限循环不停止f.put(0); //结束符// 3D 立方体点数据vector verts {{-1,-1,1}, {1,-1,1}, {1,1,1}, {-1,1,1},{-1,-1,-1}, {1,-1,-1}, {1,1,-1}, {-1,1,-1}};vector edges {{0,1},{1,2},{2,3},{3,0}, {4,5},{5,6},{6,7},{7,4}, {0,4},{1,5},{2,6},{3,7}};cout Encoding 3D Cube to GIF... endl;for (int i 0; i 60; i) { // 60帧动画vector pixels(W * H, 0); // 黑色背景float angle i * 0.12f; // 每1/60s旋转角度vector p2d;for (auto v : verts)p2d.push_back(project(rotate(v, angle), W, H)); // 3D-2D投影for (auto e : edges)drawLine(pixels, W, H, p2d[e.u].first, p2d[e.u].second, p2d[e.v].first, p2d[e.v].second); // 画边writeGifFrame(f, pixels, W, H); // 写入帧数据cout .;}f.put(0x3B); // 文件结束符f.close(); //关闭cout \nSuccess! Open cube_perfect.gif in Chrome/Edge. endl;return 0;}运行这段代码你会惊讶地发现目录下多了一个 cube_perfect.gif。用浏览器打开它一个绿色的线框立方体正在黑色的背景中流畅地旋转。5. 打通认知的“任督二脉”回顾这个系列的三篇文章我们其实只做了一件事祛魅Demystification。WAV 篇我们发现声音文件只是记录振幅的二进制队列没有任何魔法。3D 篇我们发现那些酷炫的 3D 游戏底层只是初中几何的“相似三角形”运算。GIF 篇本文我们将数学运算的结果3D按照文件协议二进制封装成了人类可见的动画。这就是计算机科学最迷人的地方。无论是生成一段 440Hz 的正弦波还是渲染《黑神话悟空》中复杂的场景其本质都是一样的Input数据 Rules算法/格式 Output数字世界俨廊卦刭

相关文章:

Spring with AI (): 搜索扩展——向量数据库与RAG(下)谋

. GIF文件结构 相比于 WAV 文件的简单粗暴,GIF 的结构要精密得多,因为它天生是为了网络传输而设计的(包含了压缩机制)。 当我们用二进制视角观察 GIF 时,它是由一个个 数据块(Block) 组成的&…...

太空探索与宇宙概述

推动太空探索的技术 太空探索是由航空航天工程、机器人技术和卫星技术的进步所推动的,融合了科学、技术和创新的跨学科领域。其总体目标是探索天体、研究宇宙现象,并解开有关宇宙起源、演化以及地外生命存在可能性的关键问题。 火箭技术。太空探索中最基…...

HUB75Enano:Arduino Nano 的轻量级 HUB75E 显示驱动库

1. HUB75Enano 库深度技术解析:面向 Arduino Nano 的紧凑型 HUB75E 显示驱动方案1.1 项目定位与工程约束本质HUB75Enano 是一个专为资源极度受限的 AVR 平台(特别是 ATmega328P)设计的 HUB75E 接口 LED 矩阵驱动库。其核心价值不在于功能堆砌…...

营销管理5步流程指南

什么是营销管理流程? 营销管理流程是一种规划、组织和控制一个组织的营销活动的方法。营销管理流程是一套系统性的步骤,帮助企业通过满足客户需求来实现其目标。营销管理流程中的每一个步骤都帮助企业实现这些目标。 营销流程始于定义公司的组织目标和目…...

OpenClaw模型热切换:Qwen3.5-9B不同量化版本在线对比

OpenClaw模型热切换:Qwen3.5-9B不同量化版本在线对比 1. 为什么需要模型热切换 上周我在用OpenClaw处理一批产品截图分析任务时,遇到了一个典型的技术选择困境:4bit量化的Qwen3.5-9B模型虽然推理速度快,但在处理复杂场景图片时经…...

Vue 渲染器 Renderer 是如何工作的?跨平台渲染虚拟 DOM 的底层架构

Vue渲染器是将虚拟DOM转换为真实平台视图的可配置引擎,通过宿主接口实现跨平台适配,核心职责为创建、更新、卸载节点,依赖patch函数协调新旧vnode同步。Vue 的渲染器(Renderer)本质是一套将虚拟 DOM 转换为真实平台视图…...

盲人辅助工具:OpenClaw+Gemma-3-12b-it的屏幕阅读增强方案

盲人辅助工具:OpenClawGemma-3-12b-it的屏幕阅读增强方案 1. 为什么需要这个方案 作为一个长期关注无障碍技术的开发者,我一直在寻找能够真正帮助视障用户的技术方案。传统的屏幕阅读器虽然成熟,但存在几个明显的痛点: 机械化的…...

OpenClaw云端体验:通过星图平台快速部署千问3.5-35B-A3B-FP8

OpenClaw云端体验:通过星图平台快速部署千问3.5-35B-A3B-FP8 1. 为什么选择云端体验OpenClaw 第一次接触OpenClaw时,我被它的本地自动化能力吸引,但很快遇到了现实问题——在自己的MacBook Pro上配置Python环境、解决依赖冲突、调试模型连接…...

从零搭建本地版 Claurst:基于 Rust 重构的 Claude Code 终端编码助手 + LM Studio 模型接入测试

从零搭建本地版 Claurst:基于 Rust 重构的 Claude Code 终端编码助手 LM Studio 模型接入测试 Kuberwastaken/claurst: Your favorite Terminal Coding Agent, now in Rust Claurst 是一款基于 Rust 重构的开源终端编码助手,复刻了 Claude Code 的核心交…...

Flutter中StatefulWidget的生命周期

在 Flutter 中&#xff0c;StatefulWidget 的生命周期实际上是由其关联的 State<T> 对象管理的。掌握这些生命周期方法对于正确初始化资源、响应状态变化、避免内存泄漏以及优化渲染性能至关重要。 以下是 StatefulWidget 的完整生命周期解析&#xff1a; &#x1f501; …...

太阳能监控哪家强?商用品牌大揭秘,省钱省心这样选!

在工商业安防、交通管理、野外监测等领域&#xff0c;太阳能监控系统以其无需市电、部署灵活、绿色节能的优势&#xff0c;正成为解决偏远无电区域监控难题的首选方案。然而&#xff0c;面对市场上琳琅满目的品牌和产品&#xff0c;如何选择一个真正“强”且适合商用场景的解决…...

红黑树:从入门到精通的C++实战

从零到一掌握红黑树&#xff1a;数据结构中的平衡之道红黑树是一种自平衡的二叉搜索树&#xff0c;它通过颜色属性和特定规则来确保树的高度大致平衡&#xff0c;从而保证查找、插入和删除操作的时间复杂度为$O(\log n)$。在C中&#xff0c;红黑树常用于实现标准库中的std::map…...

Pi0模型快速体验:一键启动Web演示,免配置玩转机器人控制

Pi0模型快速体验&#xff1a;一键启动Web演示&#xff0c;免配置玩转机器人控制 1. 项目概述 Pi0是一个创新的视觉-语言-动作流模型&#xff0c;专为通用机器人控制设计。这个项目最吸引人的地方在于它提供了一个开箱即用的Web演示界面&#xff0c;让用户无需复杂的配置就能体…...

OpenClaw多模型切换指南:Phi-3-vision-128k-instruct与纯文本模型协同工作

OpenClaw多模型切换指南&#xff1a;Phi-3-vision-128k-instruct与纯文本模型协同工作 1. 为什么需要多模型协同 去年我在尝试用AI自动化处理日常工作时&#xff0c;发现一个尴尬的现象&#xff1a;当我需要处理图文混合内容时&#xff0c;调用纯文本模型效果惨不忍睹&#x…...

InstructPix2Pix企业落地:内容团队降本增效的AI修图SOP制定指南

InstructPix2Pix企业落地&#xff1a;内容团队降本增效的AI修图SOP制定指南 1. 引言&#xff1a;当AI修图师走进企业内容团队 想象一下这样的场景&#xff1a;电商团队需要为同一款商品制作不同季节的营销图&#xff0c;设计部门正在为节日活动准备上百张海报&#xff0c;内容…...

ClearerVoice-Studio功能全解析:语音增强、分离、提取,哪个最适合你?

ClearerVoice-Studio功能全解析&#xff1a;语音增强、分离、提取&#xff0c;哪个最适合你&#xff1f; 1. 语音处理技术现状与需求 在数字时代&#xff0c;清晰的语音已成为沟通的基础需求。无论是远程会议、内容创作还是多媒体制作&#xff0c;我们经常面临以下挑战&#…...

HEX与BIN文件格式详解及嵌入式开发应用

1. 文件格式的本质差异第一次接触单片机开发时&#xff0c;我也曾被HEX和BIN文件搞得晕头转向。直到有次烧录出错导致硬件锁死&#xff0c;才真正明白这两种格式的区别绝非表面那么简单。HEX文件本质上是一种带地址信息的文本编码格式&#xff0c;而BIN文件则是纯粹的二进制映像…...

小白必看:cv_resnet18_ocr-detection WebUI界面详解,功能一目了然

小白必看&#xff1a;cv_resnet18_ocr-detection WebUI界面详解&#xff0c;功能一目了然 1. 快速认识cv_resnet18_ocr-detection 如果你正在寻找一个简单好用的文字识别工具&#xff0c;cv_resnet18_ocr-detection绝对值得一试。这个由科哥开发的OCR文字检测模型&#xff0c…...

嵌入式开发必备终端工具与效率提升技巧

1. 项目概述作为一名在嵌入式领域摸爬滚打十多年的老工程师&#xff0c;我深知终端工具对开发效率的决定性影响。今天要分享的这些"终端神器"&#xff0c;都是我在实际项目中反复验证过的效率加速器。它们不是那些花里胡哨的新潮工具&#xff0c;而是经过时间考验的实…...

OpenClaw+千问3.5-9B自动化报告:从数据到PPT一键生成

OpenClaw千问3.5-9B自动化报告&#xff1a;从数据到PPT一键生成 1. 为什么需要自动化报告系统 每周五下午三点&#xff0c;我的日历总会准时弹出提醒&#xff1a;"准备本周工作报告"。这个重复性任务通常要耗费1-2小时&#xff1a;从数据库导出CSV、用Excel制作图表…...

OpenClaw+Qwen2.5-VL-7B:低成本自动化内容生成方案

OpenClawQwen2.5-VL-7B&#xff1a;低成本自动化内容生成方案 1. 为什么选择这个组合 去年我开始尝试用AI辅助内容创作时&#xff0c;遇到了两个核心痛点&#xff1a;一是商业API调用成本太高&#xff0c;二是现有工具无法实现端到端的自动化。经过多次尝试&#xff0c;最终找…...

光储微网ODM/OEM标杆实践:爱阳储能的技术深耕与全场景赋能之路

在双碳目标推动下&#xff0c;全球储能产业进入规模化爆发期&#xff0c;分布式储能作为能源结构转型的核心支撑&#xff0c;正迎来前所未有的发展机遇。其中&#xff0c;ODM/OEM模式凭借柔性定制、技术适配、成本优化的核心优势&#xff0c;成为连接储能技术研发与全球市场需求…...

工商业储能柜的 OEM 定制需要关注哪些关键指标?

“同一款工商业储能柜&#xff0c;为什么不同工厂的报价差异能达到 30%&#xff1f;” 这是不少储能贸易商在筛选供应商时遇到的典型问题。随着国内峰谷电价差持续拉大&#xff0c;工商业储能需求快速释放&#xff0c;但面对市场上五花八柜的产品方案&#xff0c;贸易商往往难以…...

LeetCode 3740. 三个相等元素之间的最小距离 I, 3741. 三个相等元素之间的最小距离 II【按照相同元素分组】中等

本文属于「征服LeetCode」系列文章之一&#xff0c;这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁&#xff0c;本系列将至少持续到刷完所有无锁题之日为止&#xff1b;由于LeetCode还在不断地创建新题&#xff0c;本系列的终止日期可能是永远。在这一系列刷题文章…...

ERTEC 系列 PROFINET 芯片级硬件过滤器分析仓

一、语言特性&#xff1a;Java 26 与模式匹配进化 1.1 Java 26 语言级别支持 IDEA 2026.1 EAP 最引人注目的变化之一&#xff0c;就是新增 Java 26 语言级别支持。这意味着开发者可以提前体验和测试即将在 JDK 26 中正式发布的语言特性。 其中最重要的变化是对 JEP 530 的全…...

SparkFun Qwiic OLED Arduino图形库深度解析

1. 项目概述 SparkFun Qwiic OLED Arduino Library 是一个面向嵌入式显示应用的轻量级、高效率图形驱动库&#xff0c;专为 SparkFun 全系列基于 SSD1306 控制器的 Qwiic 接口 OLED 模块设计。该库并非简单封装&#xff0c;而是从底层硬件抽象层出发&#xff0c;重构了图形渲染…...

3步实现Windows系统全面优化:开源工具的智能解决方案

3步实现Windows系统全面优化&#xff1a;开源工具的智能解决方案 【免费下载链接】Winhance-zh_CN A Chinese version of Winhance. C# application designed to optimize and customize your Windows experience. 项目地址: https://gitcode.com/gh_mirrors/wi/Winhance-zh_…...

超级个体时代:一人公司+AI Agent军团

超级个体时代:一人公司+AI Agent军团 1. 引入与连接:当一个人成为一支军队 1.1 开场故事:未来已来,只是分布不均 2023年的一个平凡早晨,32岁的独立开发者李明醒来,像往常一样打开了他的"指挥中心"——一个由多个显示屏组成的工作台。但与大多数上班族不同,李…...

Python数据分析项目实战(049)——DataFrame数据类型转换

版权声明 本文原创作者:谷哥的小弟 作者博客地址:http://blog.csdn.net/lfdfhl 数据类型转换概述 数据类型转换是数据预处理中规范数据格式、适配分析需求的核心操作,指将DataFrame中字段的原始数据类型(如字符串、整数、浮点数等)转换为目标类型的过程,其本质是解决“数…...

使用Alpine配置WSL ssh门户鼐

1. 哑铃图是什么&#xff1f; 哑铃图&#xff08;Dumbbell Plot&#xff09;&#xff0c;有时也称为DNA图或杠铃图&#xff0c;是一种用于比较两个相关数据点的可视化图表。 它源于人们对更有效数据比较方式的持续探索。 在传统的时间序列比较中&#xff0c;我们通常使用两条折…...