news 2026/5/3 1:11:01

【计算机视觉-作业1】从图像到向量:kNN数据预处理完整流程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【计算机视觉-作业1】从图像到向量:kNN数据预处理完整流程

文章目录

    • 一、数据流程(5步走)
      • 第1步:原始数据是什么?
      • 第2步:加载数据(把文件读成数组)
      • 第3步:采样(减少数量,加快实验)
      • 第4步:展平成向量(最关键!)
      • 第5步:计算L2距离
    • 二、图片如何被"压扁"?用例子说明
      • 例子1:2×2的小图片(理解原理)
      • 例子2:32×32的真实图片
    • 三、reshape的工作原理
    • 四、实际代码演示

kNN需要向量才能算距离,所以必须把图片从(32, 32, 3)展平成(3072,)向量。每个3072维向量就是一张图片的所有像素信息排成一行。

类比:就像把一张照片从左到右、从上到下扫描一遍,变成一串数字,然后比较两串数字的相似程度。

整体流程:图像文件 → 加载成数组 → 采样减少数量 → 展平成向量 → 计算距离


一、数据流程(5步走)

第1步:原始数据是什么?

CIFAR-10数据集:5万个训练图片 + 1万个测试图片,每张图片32×32像素,RGB彩色。

存储格式:存在pickle文件里,每个文件存1万张图片。图片被压扁成一串数字:(10000, 3072),3072 = 32×32×3(宽×高×RGB)。

第2步:加载数据(把文件读成数组)

代码cs231n/data_utils.py):

defload_CIFAR_batch(filename):withopen(filename,'rb')asf:datadict=load_pickle(f)X=datadict['data']# 形状 (10000, 3072) - 一串数字Y=datadict['labels']# 10000个标签# 重新整理成图片格式X=X.reshape(10000,3,32,32)# 变成 (10000, 3, 32, 32)X=X.transpose(0,2,3,1)# 变成 (10000, 32, 32, 3)X=X.astype("float")# 转成浮点数returnX,Y

代码解释

  • reshape(10000, 3, 32, 32):把3072个数字重新排列,变成3个通道、每个32×32的图片
  • transpose(0,2,3,1):调整维度顺序,从(通道,高,宽)变成(高,宽,通道),这样Matplotlib才能正确显示
  • astype("float"):把整数像素值(0-255)转成浮点数,方便计算

加载完整数据集

defload_CIFAR10(ROOT):xs,ys=[],[]# 加载5个训练批次forbinrange(1,6):X,Y=load_CIFAR_batch(f'data_batch_{b}')xs.append(X)# 每个X形状 (10000, 32, 32, 3)ys.append(Y)# 合并所有训练数据Xtr=np.concatenate(xs)# (50000, 32, 32, 3)Ytr=np.concatenate(ys)# (50000,)# 加载测试数据Xte,Yte=load_CIFAR_batch('test_batch')returnXtr,Ytr,Xte,Yte

结果

  • 训练集:5个文件合并 →(50000, 32, 32, 3)(5万张图片)
  • 测试集:1个文件 →(10000, 32, 32, 3)(1万张图片)

第3步:采样(减少数量,加快实验)

代码knn.ipynb):

# 采样训练数据num_training=5000mask=list(range(num_training))X_train=X_train[mask]# 从50000采样到5000y_train=y_train[mask]# 采样测试数据num_test=500mask=list(range(num_test))X_test=X_test[mask]# 从10000采样到500y_test=y_test[mask]

代码解释

  • list(range(5000)):生成索引[0,1,2,…,4999]
  • X_train[mask]:用索引切片,只取前5000个样本
  • 为什么采样?数据太多算得慢,先拿一部分试试效果

结果

  • 训练集:(5000, 32, 32, 3)
  • 测试集:(500, 32, 32, 3)

第4步:展平成向量(最关键!)

代码knn.ipynb):

# Reshape the image data into rowsX_train=np.reshape(X_train,(X_train.shape[0],-1))X_test=np.reshape(X_test,(X_test.shape[0],-1))print(X_train.shape,X_test.shape)# 输出: (5000, 3072) (500, 3072)

代码解释

  • X_train.shape[0]:第一维大小,即5000(样本数)
  • -1:自动计算,-1 = 32×32×3 = 3072
  • reshape(5000, -1):保持5000行,把后面的维度展平成一列

第5步:计算L2距离

现在每张图片都是向量了,可以算距离了:

代码knn.ipynb):

classifier=KNearestNeighbor()classifier.train(X_train,y_train)# 只是保存数据,不训练dists=classifier.compute_distances_two_loops(X_test)# dists 形状: (500, 5000)# dists[i, j] = 第i个测试图片和第j个训练图片的距离

距离计算代码k_nearest_neighbor.py):

defcompute_distances_two_loops(self,X):num_test=X.shape[0]# 500num_train=self.X_train.shape[0]# 5000dists=np.zeros((num_test,num_train))foriinrange(num_test):forjinrange(num_train):# 计算L2距离:对应位置相减、平方、求和、开根号dists[i,j]=np.sqrt(np.sum((X[i]-self.X_train[j])**2))returndists

代码解释

  • X[i]:第i个测试样本,形状(3072,)
  • self.X_train[j]:第j个训练样本,形状(3072,)
  • (X[i] - self.X_train[j]):对应位置相减,形状(3072,)
  • ** 2:每个元素平方
  • np.sum(...):求和,得到一个数
  • np.sqrt(...):开根号,得到距离

距离公式d = ∑ k = 1 3072 ( x k − y k ) 2 d = \sqrt{\sum_{k=1}^{3072}(x_k - y_k)^2}d=k=13072(xkyk)2,就是两个向量对应位置差的平方和再开根号。


二、图片如何被"压扁"?用例子说明

例子1:2×2的小图片(理解原理)

假设有一张2×2像素的RGB图片,形状是(2, 2, 3)

# 原始图片 (2, 2, 3)image=[# 第1行[[100,150,200],# 像素(0,0): R=100, G=150, B=200[110,160,210]],# 像素(0,1): R=110, G=160, B=210# 第2行[[120,170,220],# 像素(1,0): R=120, G=170, B=220[130,180,230]]# 像素(1,1): R=130, G=180, B=230]

展平过程

# 用reshape展平vector=np.reshape(image,(-1,))# 结果: [100, 150, 200, 110, 160, 210, 120, 170, 220, 130, 180, 230]# ↑像素(0,0)↑ ↑像素(0,1)↑ ↑像素(1,0)↑ ↑像素(1,1)↑

规律:按行优先顺序,从左到右、从上到下,把每个像素的RGB值依次排列。

例子2:32×32的真实图片

一张32×32的RGB图片,形状是(32, 32, 3)

# 原始图片 (32, 32, 3)image=[# 第1行(32个像素)[[R00,G00,B00],[R01,G01,B01],...,[R0_31,G0_31,B0_31]],# 第2行(32个像素)[[R10,G10,B10],[R11,G11,B11],...,[R1_31,G1_31,B1_31]],# ...# 第32行(32个像素)[[R31_0,G31_0,B31_0],...,[R31_31,G31_31,B31_31]]]

展平过程

vector=np.reshape(image,(-1,))# 结果: [R00, G00, B00, R01, G01, B01, ..., R0_31, G0_31, B0_31,# R10, G10, B10, R11, G11, B11, ..., R1_31, G1_31, B1_31,# ...# R31_0, G31_0, B31_0, ..., R31_31, G31_31, B31_31]

长度计算:32行 × 32列 × 3通道 = 3072个数字


三、reshape的工作原理

reshape不改变数据,只改变排列方式

# 原始数据在内存中是一串连续的数字# reshape只是告诉NumPy如何解释这串数字# 例子:12个数字data=[1,2,3,4,5,6,7,8,9,10,11,12]# 解释成 2×2×3 的图片image=np.reshape(data,(2,2,3))# [[[1, 2, 3], [4, 5, 6]],# [[7, 8, 9], [10, 11, 12]]]# 解释成 12 的向量(展平)vector=np.reshape(image,(-1,))# [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]# 数据没变,只是形状变了!

关键理解

  • 数据在内存中就是一串连续的数字
  • reshape只是改变如何解释这串数字
  • (32, 32, 3)变成(3072,),数据本身没变,只是从"三维表格"变成了"一维列表"

四、实际代码演示

importnumpyasnp# 创建一张2×2的RGB图片(随机值)image=np.random.randint(0,255,(2,2,3))print("原始图片形状:",image.shape)# (2, 2, 3)print("原始图片:\n",image)# [[[100 150 200]# [110 160 210]]# [[120 170 220]# [130 180 230]]]# 展平vector=np.reshape(image,(-1,))print("\n展平后形状:",vector.shape)# (12,)print("展平后:",vector)# [100 150 200 110 160 210 120 170 220 130 180 230]# 验证:可以还原回去image2=np.reshape(vector,(2,2,3))print("\n还原后是否相同:",np.array_equal(image,image2))# True

32×32图片的展平过程(可视化)

原始图片 (32, 32, 3): ┌─────────────────────────┐ │ [R G B] [R G B] ... │ ← 第1行,32个像素 │ [R G B] [R G B] ... │ ← 第2行,32个像素 │ ... │ │ [R G B] [R G B] ... │ ← 第32行,32个像素 └─────────────────────────┘ ↓ reshape ↓ 展平向量 (3072,): [R G B R G B ... R G B R G B ... ... R G B ... R G B] ↑第1行↑ ↑第2行↑ ↑第32行↑

结果:每张图片变成一个3072维的向量(一串3072个数字)。

数据形状变化表

步骤训练集测试集说明
文件里(10000, 3072)(10000, 3072)压扁的数字
加载后(50000, 32, 32, 3)(10000, 32, 32, 3)图片格式
采样后(5000, 32, 32, 3)(500, 32, 32, 3)减少数量
展平后(5000, 3072)(500, 3072)向量格式
距离矩阵-(500, 5000)测试×训练

为什么是3072维?

  • 32 × 32 = 1024(像素数)
  • 1024 × 3 = 3072(每个像素有RGB三个通道)
  • 所以每张图片展平后是3072个数字
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/1 8:32:35

Qwen2.5-VL-7B-Instruct新手指南:从安装到视频分析的完整流程

Qwen2.5-VL-7B-Instruct新手指南:从安装到视频分析的完整流程 你是否试过把一张截图发给AI,让它准确说出图中表格的每一行数据?或者上传一段会议录像,让它自动定位并总结关键发言片段?这些曾经需要复杂工程搭建的任务…

作者头像 李华
网站建设 2026/5/2 15:54:17

万物识别-中文-通用领域部署避坑:Conda环境配置注意事项

万物识别-中文-通用领域部署避坑:Conda环境配置注意事项 1. 这个模型到底能认出什么? 你有没有试过拍一张街边小店的招牌照片,想让它告诉你上面写了啥?或者随手拍张超市货架的照片,希望它能列出所有商品名称&#xf…

作者头像 李华
网站建设 2026/5/1 7:32:03

QtScrcpy:无线投屏与多设备控制的全方位解决方案

QtScrcpy:无线投屏与多设备控制的全方位解决方案 【免费下载链接】QtScrcpy QtScrcpy 可以通过 USB / 网络连接Android设备,并进行显示和控制。无需root权限。 项目地址: https://gitcode.com/GitHub_Trending/qt/QtScrcpy 您是否曾遇到过手机屏幕…

作者头像 李华
网站建设 2026/5/1 7:30:59

3款多模态模型部署测评:Qwen3-VL-2B CPU版表现惊艳

3款多模态模型部署测评:Qwen3-VL-2B CPU版表现惊艳 1. 为什么这次CPU版多模态模型值得你停下来看一眼 你有没有试过在没有显卡的笔记本上跑多模态模型?大概率是点开网页就卡住,加载十分钟没反应,或者干脆报错“CUDA out of memo…

作者头像 李华
网站建设 2026/5/2 10:11:05

用VibeThinker-1.5B打造专属编程助手,超简单

用VibeThinker-1.5B打造专属编程助手,超简单 你有没有过这样的时刻:刷LeetCode卡在一道中等题上,反复调试却找不到边界条件漏洞;看数学竞赛题干三遍,仍理不清逻辑链条;或者想快速验证一个算法思路&#xf…

作者头像 李华