第六篇:图片也能变成数字吗?——用像素讲透图片向量化

张开发
2026/4/20 19:50:48 15 分钟阅读

分享文章

第六篇:图片也能变成数字吗?——用像素讲透图片向量化
第六篇图片也能变成数字吗——用像素讲透图片向量化前言前面五篇文章我们一直在讲文本向量化把文字变成数字。但你有没有想过图片也能变成数字吗答案是当然可以而且原理和文本向量化惊人地相似。这篇文章我们用最简单的像素值法带你理解图片向量化的核心思想。读完这篇你就会明白图片是怎么变成数字的为什么可以用余弦相似度比较图片图片向量化的实际应用场景一、先看一张图片1.1 电脑眼中的图片在你眼里这是阿尔忒弥斯2号的发射图片但在电脑眼里这张图片是这样的[[255, 200, 150], [250, 195, 145], [248, 190, 140], ...] [[253, 198, 148], [255, 200, 150], [251, 196, 146], ...] [[250, 195, 145], [249, 193, 143], [255, 200, 150], ...] ...这是什么这是一个三维数组每个数字代表一个像素的颜色值。1.2 像素是什么把图片放大很多倍你会看到一个个小方块┌───┬───┬───┬───┬───┐ │255│250│248│253│255│ ← 每个数字是一个像素 ├───┼───┼───┼───┼───┤ │200│195│190│198│200│ ├───┼───┼───┼───┼───┤ │150│145│140│148│150│ └───┴───┴───┴───┴───┘每个像素有3个值R红、G绿、B蓝范围是0-255。一个像素 [R, G, B] 例如[255, 200, 150] 表示橙红色1.3 图片 一堆数字一张 100×100 的彩色图片在电脑眼里就是100行 × 100列 × 3个颜色通道 30000个数字这不就是向量吗对把所有数字排成一排就是一个30000维的向量二、图片向量化的三种方法2.1 方法一像素值法最简单核心思想直接把所有像素的RGB值排成一排。图片 → RGB数组 → 一维向量 例如2×2的小图片 ┌─────┬─────┐ │[R,G,B]│[R,G,B]│ ├─────┼─────┤ │[R,G,B]│[R,G,B]│ └─────┴─────┘ 变成向量 [R₁,G₁,B₁, R₂,G₂,B₂, R₃,G₃,B₃, R₄,G₄,B₄]优点简单直观容易理解保留所有原始信息缺点向量维度很高100×100图片 30000维对图片大小、位置敏感2.2 方法二颜色直方图法常用核心思想统计每种颜色出现的次数忽略位置。图片 → 统计颜色分布 → 直方图向量 例如 红色出现100次 蓝色出现200次 绿色出现150次 ... 向量 [100, 200, 150, ...]优点向量维度固定通常256维或更少不受图片缩放影响不受物体位置影响缺点丢失了位置信息不同图片可能有相似的颜色分布2.3 方法三深度学习法最先进核心思想用神经网络提取图片的特征。图片 → CNN神经网络 → 特征向量通常512或1024维优点提取语义特征能识别火箭、月球等概念向量维度合理效果最好缺点需要预训练模型原理复杂不够直观三、用像素值法实现图片相似度检测我们用最简单的像素值法来检测两张图片是否相似。3.1 准备两张测试图片我们用两张简单的 4×4 灰度图来演示// 图片A左上角亮varimageA[][]float64{{200,150,100,50},{180,130,80,40},{160,110,60,30},{140,90,40,20},}// 图片B和A很相似只是整体暗一点varimageB[][]float64{{180,130,80,40},{160,110,60,30},{140,90,40,20},{120,70,30,10},}// 图片C和A完全不同右上角亮varimageC[][]float64{{50,100,150,200},{40,80,130,180},{30,60,110,160},{20,40,90,140},}3.2 把图片转成向量// 把二维图片转成一维向量funcimageToVector(image[][]float64)[]float64{varvector[]float64for_,row:rangeimage{vectorappend(vector,row...)}returnvector}测试一下vectorA:imageToVector(imageA)vectorB:imageToVector(imageB)vectorC:imageToVector(imageC)fmt.Printf(向量A: %v\n,vectorA)fmt.Printf(向量B: %v\n,vectorB)fmt.Printf(向量C: %v\n,vectorC)输出向量A: [200 150 100 50 180 130 80 40 160 110 60 30 140 90 40 20] 向量B: [180 130 80 40 160 110 60 30 140 90 40 20 120 70 30 10] 向量C: [50 100 150 200 40 80 130 180 30 60 110 160 20 40 90 140]3.3 用余弦相似度比较图片复用第三篇文章的余弦相似度函数// 计算余弦相似度funccosineSimilarity(a,b[]float64)float64{// 第一步算点积dotProduct:0.0fori:rangea{dotProducta[i]*b[i]}// 第二步算各自的长度lengthA:0.0lengthB:0.0fori:rangea{lengthAa[i]*a[i]lengthBb[i]*b[i]}lengthAmath.Sqrt(lengthA)lengthBmath.Sqrt(lengthB)// 第三步点积除以长度乘积iflengthA0||lengthB0{return0}returndotProduct/(lengthA*lengthB)}计算相似度simAB:cosineSimilarity(vectorA,vectorB)simAC:cosineSimilarity(vectorA,vectorC)fmt.Printf(图片A和B的相似度: %.4f\n,simAB)fmt.Printf(图片A和C的相似度: %.4f\n,simAC)输出图片A和B的相似度: 0.9962 图片A和C的相似度: 0.7832结果分析A和B相似度 0.9962 → 非常相似符合预期B只是A的暗版A和C相似度 0.7832 → 不太相似符合预期C是A的镜像3.4 完整代码packagemainimport(fmtmath)// 图片数据4×4灰度图varimageA[][]float64{{200,150,100,50},{180,130,80,40},{160,110,60,30},{140,90,40,20},}varimageB[][]float64{{180,130,80,40},{160,110,60,30},{140,90,40,20},{120,70,30,10},}varimageC[][]float64{{50,100,150,200},{40,80,130,180},{30,60,110,160},{20,40,90,140},}// 把图片转成向量funcimageToVector(image[][]float64)[]float64{varvector[]float64for_,row:rangeimage{vectorappend(vector,row...)}returnvector}// 计算余弦相似度funccosineSimilarity(a,b[]float64)float64{dotProduct:0.0fori:rangea{dotProducta[i]*b[i]}lengthA:0.0lengthB:0.0fori:rangea{lengthAa[i]*a[i]lengthBb[i]*b[i]}lengthAmath.Sqrt(lengthA)lengthBmath.Sqrt(lengthB)iflengthA0||lengthB0{return0}returndotProduct/(lengthA*lengthB)}funcmain(){fmt.Println( 图片相似度检测演示 )fmt.Println()// 转成向量vectorA:imageToVector(imageA)vectorB:imageToVector(imageB)vectorC:imageToVector(imageC)fmt.Printf(图片A向量: %v\n,vectorA)fmt.Printf(图片B向量: %v\n,vectorB)fmt.Printf(图片C向量: %v\n,vectorC)fmt.Println()// 计算相似度simAB:cosineSimilarity(vectorA,vectorB)simAC:cosineSimilarity(vectorA,vectorC)fmt.Printf(图片A和B的相似度: %.4f\n,simAB)fmt.Printf(图片A和C的相似度: %.4f\n,simAC)fmt.Println()// 结论fmt.Println(结论)ifsimABsimAC{fmt.Println( 图片B和A更相似 ✓)}else{fmt.Println( 图片C和A更相似 ✓)}fmt.Println()fmt.Println( 演示结束 )}运行结果 图片相似度检测演示 图片A向量: [200 150 100 50 180 130 80 40 160 110 60 30 140 90 40 20] 图片B向量: [180 130 80 40 160 110 60 30 140 90 40 20 120 70 30 10] 图片C向量: [50 100 150 200 40 80 130 180 30 60 110 160 20 40 90 140] 图片A和B的相似度: 0.9962 图片A和C的相似度: 0.7832 结论 图片B和A更相似 ✓ 演示结束 四、为什么余弦相似度也能用于图片4.1 核心原理方向一致 内容相似还记得第三篇讲的吗余弦相似度只看方向不看长度。对于图片来说方向 像素的相对关系明暗分布长度 像素的绝对值整体亮度图片A整体较亮 [200, 150, 100, 50] 图片B整体较暗 [180, 130, 80, 40] 方向一致都是左上角最亮→ 相似度高 长度不同B整体暗一些→ 不影响相似度4.2 用生活比喻来理解想象你在拍照场景一晴天拍埃菲尔铁塔场景二阴天拍埃菲尔铁塔两张照片的亮度不同但拍的都是埃菲尔铁塔。余弦相似度就是把两张照片亮度归一化然后比较内容方向忽略亮度长度五、实际应用场景5.1 图片搜索用户上传一张火箭图片系统从数据库中找到相似的火箭图片。流程 1. 用户上传图片 2. 图片转成向量 3. 在向量数据库中检索 4. 返回相似的图片5.2 图片去重判断两张图片是否相同或相似用于社交媒体去重版权检测数据集清洗5.3 商品推荐用户看了一件商品系统推荐相似的商品用户看一件红色连衣裙 系统推荐相似款式的红色连衣裙5.4 人脸识别把人脸转成向量比较相似度用户人脸向量 vs 数据库人脸向量 相似度 阈值 → 认证成功 相似度 阈值 → 认证失败六、像素值法的局限性6.1 问题一对缩放敏感原图100×100 缩放后200×200 向量维度不同无法直接比较解决方案预处理把所有图片缩放到相同尺寸使用颜色直方图法不受尺寸影响6.2 问题二对位置敏感图片A火箭在左边 图片B火箭在右边内容相同 像素值法会认为不相似解决方案使用颜色直方图法忽略位置使用深度学习法提取语义特征6.3 问题三向量维度高100×100彩色图片 100×100×3 30000维 维度太高计算慢存储大解决方案使用颜色直方图法通常256维使用深度学习法通常512或1024维七、三种方法对比方法原理维度优点缺点像素值法直接排成向量高简单直观保留所有信息对缩放、位置敏感颜色直方图统计颜色分布低不受尺寸、位置影响丢失位置信息深度学习神经网络提取特征中提取语义特征效果最好需要预训练模型八、总结8.1 图片向量化的核心思想图片 → 像素值 → 向量 → 余弦相似度 → 判断是否相似8.2 与文本向量化的对比特性文本向量化图片向量化基本单位词像素向量化方法词频统计像素值/直方图/深度学习相似度计算余弦相似度余弦相似度核心思想把文字变成数字把图片变成数字8.3 关键结论图片 一堆数字像素值向量化的思想是通用的不只是文本余弦相似度可以比较任何向量文本、图片、音频等后记恭喜你读完第六篇现在你已经理解了向量化的本质把任何东西变成数字然后用数学方法处理。文本 → 词频向量 → 余弦相似度图片 → 像素向量 → 余弦相似度向量化是AI的基础语言。系列文章Go Ollama 构建tinyRAG应用Prompt提示工程用阿尔忒弥斯2号讲透文本向量化一眼看穿相似度余弦相似度原理详解手把手实现文本向量数据库从问题到答案一个完整的RAG系统是如何工作的本文图片也能变成数字吗——用像素讲透图片向量化

更多文章